Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .claude/custom-lint-rules.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,92 @@ steps = [
[rules.example]
bad = '具体的なファイル所在: `C:\Users\alice\.claude\projects\<project-id>\` 配下'
good = '具体的なファイル所在: `%USERPROFILE%\.claude\projects\<project-id>\` 配下'

# ─── ルール③: PowerShell 空 catch ブロック禁止 (swallowed error) ───
#
# 由来: PR #85 で `__parse_transcripts.ps1:8` の空 `catch {}` が CodeRabbit Major 指摘。
# Review Policy 明示的 REJECT 項目「Swallowed errors」。エラー握り潰しは debug 困難化の
# 代表的アンチパターン。
#
# 対応する swallowed error 検出は Bash / TypeScript には既存 lint があるが、
# PowerShell は ADR-007 既存ルールの空白だった。

[[rules]]
id = "no-empty-powershell-catch"
pattern = 'catch\s*\{\s*\}'
severity = "error"
message = "空の catch {} ブロックでエラーを握り潰しています"
why = "swallowed error は debug 困難化を招く Review Policy 明示的 REJECT 項目。少なくともログ出力 / 再 throw / 上位への propagate のいずれかが必要"
extensions = ["ps1"]

[rules.fix]
strategy = "ログ出力 or 再 throw or 上位 propagate のいずれかを追加"
steps = [
"意図的に無視する場合: catch ブロックに理由をコメントで明記し Write-Verbose / Write-Debug を追加",
"原因を log する場合: catch { Write-Error $_ } にする",
"上位に伝播する場合: catch { throw } にする",
"そもそも try/catch 不要なら削除する",
]

[rules.example]
bad = 'try { Get-Item $path } catch {}'
good = 'try { Get-Item $path } catch { Write-Verbose "expected miss: $_"; $null }'

# ─── ルール④: PowerShell -ErrorAction SilentlyContinue 警告 ───
#
# 由来: 同 PR #85。空 catch との組合せで二重に swallowed error を生む。
# 単独使用は一部の存在チェック (例: Get-Item -ErrorAction SilentlyContinue) で
# 正当な場合があるため severity = "warning" に留める。
# 空 catch (上の error) と同時に検出されたら、両方の violation が出力される。

[[rules]]
id = "no-silent-error-action"
pattern = '-ErrorAction\s+SilentlyContinue'
severity = "warning"
message = "-ErrorAction SilentlyContinue はエラー握り潰しのリスクがあります"
why = "存在チェックでは正当だが、結果を確認せずに使うと swallowed error。空 catch と組み合わさると二重に危険"
extensions = ["ps1"]
Comment thread
coderabbitai[bot] marked this conversation as resolved.

[rules.fix]
strategy = "戻り値を確認するか、明示的なエラーハンドリングに切替"
steps = [
"存在チェックの場合: 戻り値が $null かをチェックする",
"より明示的にしたい場合: -ErrorAction Stop + try/catch を使う",
"本当にログ抑止だけ必要な場合: -ErrorAction Ignore + コメントで理由を書く",
]

[rules.example]
bad = '$data = ConvertFrom-Json $raw -ErrorAction SilentlyContinue'
good = 'try { $data = ConvertFrom-Json $raw -ErrorAction Stop } catch { Write-Error "Invalid JSON: $_"; throw }'

# ─── ルール⑤: Markdown 非 ASCII GFM アンカー検出 (mutable anchor) ───
#
# 由来: PR #89 で CodeRabbit が `[docs/todo.md](todo.md#推奨実行順序サマリー)` を Major 指摘。
# 全リポジトリ grep で 3 ファイルにわたる同一パターンを発見。GFM の自動 anchor 生成は
# heading text のスラッグ化で日本語含む heading は脆弱な ID を生成し、heading text 変更で
# silent break する。
#
# Rust regex 制約: lookbehind 非対応のため `.md` 内で backtick (inline code) に
# 囲まれた link 例は誤検出する。本ルールを説明する文書で例を書く場合は、
# heading 自体を ASCII にするか、コード ブロックではなく説明文として書く。
# (本 TOML 自体は extensions = ["md"] にマッチしないため lint 対象外)

[[rules]]
id = "no-mutable-anchor"
pattern = '\]\([^)#]*#[^\x00-\x7F)]+'
severity = "warning"
message = "非 ASCII GFM アンカー (mutable anchor) を検出しました"
why = "GFM 自動 anchor は heading text からスラッグ化されるため、日本語見出しを参照すると heading 編集で silent break する。安定 ASCII ID を持つ <a id=\"...\"></a> 明示アンカーを使ってください"
extensions = ["md"]

[rules.fix]
strategy = "明示的な ASCII ID アンカーへの置換"
steps = [
"参照先の heading の前に <a id=\"stable-ascii-id\"></a> を追加",
"リンク側を [text](file.md#stable-ascii-id) に変更",
"或いは見出し自体を ASCII にできるならそうする",
]

[rules.example]
bad = 'See [推奨実行順序](todo.md#推奨実行順序サマリー)'
good = 'See [推奨実行順序](todo.md#recommended-order-summary) <!-- with <a id="recommended-order-summary"></a> in target file -->'
69 changes: 35 additions & 34 deletions docs/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,48 @@
---

<a id="recommended-order-summary"></a>
## 推奨実行順序サマリー (2026-04-29 更新、PR #89 post-merge-feedback 反映後)
## 推奨実行順序サマリー (2026-04-29 更新、Bundle 1 [PR #85 T1-2 + PR #89 T1-1] 完了後)

開発環境の作業効率への貢献度を基準にした推奨実行順序。詳細は各タスク冒頭の **「実行優先度」** 行を参照。

| 順位 | Tier | タスク | ファイル | 工数 | 依存 |
|---|---|---|---|---|---|
| 1 | 🚀 Tier 1 | push 前 untracked `__*` ファイル警告 hook (PR #85 T1-4) | todo2.md | Small | なし (PR #85 直接対策) |
| 2 | 🚀 Tier 1 | `cli-push-runner` jj bookmark 未設定 early-exit (PR #85 T1-3) | todo2.md | S | なし |
| 3 | 🚀 Tier 1 | PowerShell swallowed error custom_lint_rule (PR #85 T1-2) | todo2.md | XS | なし (ADR-007 拡張) |
| 4 | 🚀 Tier 1 | **Polling anti-pattern 検出ルール (PR #86 T1-1)** | todo2.md | XS | なし (PR #86 直接対策) |
| 5 | 🚀 Tier 1 | **Stop hook の `pnpm lint:md` 統合 (PR #88 T1-1)** | todo3.md | XS | なし (PR #88 直接対策、旧順位 1 完了済の gap closure) |
| 6 | 🚀 Tier 1 | **AI 生成一時スクリプト pattern の pre-push 検出 (PR #88 T1-2)** | todo3.md | Small | 順位 1 と関連 (要擦り合わせ) |
| 7 | 🚀 Tier 1 | **Markdown 非 ASCII GFM アンカー検出 lint rule (PR #89 T1-1)** | todo3.md | S | なし (PR #89 直接対策、順位 20 と二重防衛) |
| 8 | 🚀 Tier 1 | ADR-032 PR-pre: GitHub Branch Protection 整備 | todo2.md | 設定のみ | なし (依存タスクは完了済) |
| 9 | 🔧 Tier 2 | 週次レビュー (ADR-031) Phase B 実装 | todo.md | 中-高 | なし (順位 17 の compensating check 前提) |
| 10 | 🔧 Tier 2 | reviewer facet 改善 (review-simplicity / review-security の DRY/YAGNI/security 軸明文化) | todo2.md | S | なし |
| 11 | 🔧 Tier 2 | ADR-032 PR-broken-link: broken-link-check + 内部アンカー検査 統合 | todo2.md | Small-中 | なし (clean baseline 確立済) |
| 12 | 🔧 Tier 2 | `cli-pr-monitor` プロセス正常終了の integration test (PR #85 T2-2) | todo2.md | S | なし |
| 13 | 🔧 Tier 2 | **`cli-pr-monitor` ポーリング延長 + 重複起動ロック (PR #88 T2-4)** ★ rate-limit critical | todo3.md | Medium | なし (順位 4 と補完) |
| 14 | 🔧 Tier 2 | **post-pr-review に rate-limit 自動検出 + 再トリガー (PR #89 T2-1)** ★ rate-limit critical | todo3.md | Medium | なし (順位 13 と補完) |
| 15 | 🔧 Tier 2 | **`vitest` を devDependencies に固定 (PR #88 T2-3)** | todo3.md | Small | なし |
| 16 | 🔧 Tier 2 | **`pnpm create-pr` 必須引数ヘルプ改善 (PR #88 T2-5)** | todo3.md | Small | なし |
| 17 | 💎 Tier 3 | ADR-032 PR-β: 実装 (enabled=false default) | todo2.md | 中-高 | 8, 9, 11 |
| 18 | 💎 Tier 3 | ADR-032 PR-γ: enablement (1 行 flip) | todo2.md | XS | 順位 9 dogfood + 順位 17 |
| 19 | 💎 Tier 3 | ADR-032 PR-δ: dogfood + メトリクス検証 | todo2.md | (運用) | 順位 18 |
| 20 | 💎 Tier 3 | 日付ベース見出しアンカー更新ルールのグローバル明文化 (PR #85 T3-1) | todo2.md | XS | なし |
| 21 | 💎 Tier 3 | jj conflict リカバリ手順のグローバル明文化 (PR #85 T3-2) | todo2.md | XS | なし |
| 22 | 💎 Tier 3 | `__` prefix scratch file 規約のグローバル明文化 (PR #85 T3-3) | todo2.md | XS | なし |
| 23 | 💎 Tier 3 | **post-pr-monitor polling 禁止のグローバル明文化 (PR #86 T3-2)** | todo2.md | XS | なし |
| 24 | 💎 Tier 3 | **todo.md 採番管理の簡素化 ADR 起案 (PR #86 T3-3)** | todo2.md | S | なし |
| 25 | 🧹 Tier 4 | ADR-030 Phase E/F: 旧機構廃止 + dogfood | todo.md | 中 | なし (cleanup) |
| 26 | ⏳ Tier 5 | (追って) ADR-030 の takt-test-vc 反映 | todo.md | 中 | 順位 25 Phase F |

**戦略**: Tier 1 (1〜8) を 2〜3 セッションで片付け → Tier 2 (9〜16) で ADR-032 の前提を埋めつつ rate-limit 改善 (順位 13/14) → Tier 3 (17〜24) で ADR-032 を land + ドキュメント整備。Tier 4-5 (25〜26) は cleanup / 外部展開で daily efficiency への直接効果は小さい。

**順位 10 (reviewer facet 改善) は全 PR の review 精度を即時向上させ、Tier 2 内で順位 9/11/12 と並列実施可能**。
**順位 13/14 (rate-limit 系の 2 タスク) は rate-limit 直撃のため Tier 2 内で最優先候補**。順位 13 = ポーリング頻度全体の削減、順位 14 = review 単位での自動再トリガー、順位 4 (Polling anti-pattern 検出) を含む 3 層で rate-limit を抑制する設計。
**順位 5 (Stop hook の lint:md 統合) は旧順位 1 (Markdown linter hook 統合、PR #88 で merged) の gap closure**。**順位 6 (AI 生成一時スクリプト pattern 検出) は現順位 1 (push 前 untracked `__*` hook、PR #85 T1-4) と関連** (実装前に擦り合わせ要)。
**順位 7 (Markdown 非 ASCII anchor 検出 lint rule) と順位 20 (日付ベース見出しアンカー更新ルール) は二重防衛** (順位 7 = 決定論的検出、順位 20 = 編集時のガイドライン)。
**順位 20-23 (T3 グローバルルール 4 件) は `~/.claude/` 配下への XS 追記なので並列実施推奨**。
**順位 24 (採番管理簡素化 ADR) は本 table の cross-reference 維持コストを構造的に解消するメタタスク** (PR #88/#89 で連続して 30+ 箇所の renumber が発生し負債が顕在化)。
| 3 | 🚀 Tier 1 | **Polling anti-pattern 検出ルール (PR #86 T1-1)** | todo2.md | XS | なし (PR #86 直接対策) |
| 4 | 🚀 Tier 1 | **Stop hook の `pnpm lint:md` 統合 (PR #88 T1-1)** | todo3.md | XS | なし (PR #88 直接対策、旧順位 1 完了済の gap closure) |
| 5 | 🚀 Tier 1 | **AI 生成一時スクリプト pattern の pre-push 検出 (PR #88 T1-2)** | todo3.md | Small | 順位 1 と関連 (要擦り合わせ) |
| 6 | 🚀 Tier 1 | ADR-032 PR-pre: GitHub Branch Protection 整備 | todo2.md | 設定のみ | なし (依存タスクは完了済) |
| 7 | 🔧 Tier 2 | 週次レビュー (ADR-031) Phase B 実装 | todo.md | 中-高 | なし (順位 16 の compensating check 前提) |
| 8 | 🔧 Tier 2 | reviewer facet 改善 (review-simplicity / review-security の DRY/YAGNI/security 軸明文化) | todo2.md | S | なし |
| 9 | 🔧 Tier 2 | ADR-032 PR-broken-link: broken-link-check + 内部アンカー検査 統合 | todo2.md | Small-中 | なし (clean baseline 確立済) |
| 10 | 🔧 Tier 2 | `cli-pr-monitor` プロセス正常終了の integration test (PR #85 T2-2) | todo2.md | S | なし |
| 11 | 🔧 Tier 2 | **`cli-pr-monitor` ポーリング延長 + 重複起動ロック (PR #88 T2-4)** ★ rate-limit critical | todo3.md | Medium | なし (順位 3 と補完) |
| 12 | 🔧 Tier 2 | **post-pr-review に rate-limit 自動検出 + 再トリガー (PR #89 T2-1)** ★ rate-limit critical | todo3.md | Medium | なし (順位 11 と補完) |
| 13 | 🔧 Tier 2 | **`vitest` を devDependencies に固定 (PR #88 T2-3)** | todo3.md | Small | なし |
| 14 | 🔧 Tier 2 | **`pnpm create-pr` 必須引数ヘルプ改善 (PR #88 T2-5)** | todo3.md | Small | なし |
| 15 | 🔧 Tier 2 | **`.failed` marker への recovery 手順自己文書化 (PR #90 T2-2)** | todo3.md | S | なし |
| 16 | 💎 Tier 3 | ADR-032 PR-β: 実装 (enabled=false default) | todo2.md | 中-高 | 6, 7, 9 |
| 17 | 💎 Tier 3 | ADR-032 PR-γ: enablement (1 行 flip) | todo2.md | XS | 順位 7 dogfood + 順位 16 |
| 18 | 💎 Tier 3 | ADR-032 PR-δ: dogfood + メトリクス検証 | todo2.md | (運用) | 順位 17 |
| 19 | 💎 Tier 3 | 日付ベース見出しアンカー更新ルールのグローバル明文化 (PR #85 T3-1) | todo2.md | XS | なし |
| 20 | 💎 Tier 3 | jj conflict リカバリ手順のグローバル明文化 (PR #85 T3-2) | todo2.md | XS | なし |
| 21 | 💎 Tier 3 | `__` prefix scratch file 規約のグローバル明文化 (PR #85 T3-3) | todo2.md | XS | なし |
| 22 | 💎 Tier 3 | **post-pr-monitor polling 禁止のグローバル明文化 (PR #86 T3-2)** | todo2.md | XS | なし |
| 23 | 💎 Tier 3 | **todo.md 採番管理の簡素化 ADR 起案 (PR #86 T3-3)** | todo2.md | S | なし |
| 24 | 🧹 Tier 4 | ADR-030 Phase E/F: 旧機構廃止 + dogfood | todo.md | 中 | なし (cleanup) |
| 25 | ⏳ Tier 5 | (追って) ADR-030 の takt-test-vc 反映 | todo.md | 中 | 順位 24 Phase F |

**戦略**: Tier 1 (1〜6) を 2〜3 セッションで片付け → Tier 2 (7〜15) で ADR-032 の前提を埋めつつ rate-limit 改善 (順位 11/12) → Tier 3 (16〜23) で ADR-032 を land + ドキュメント整備。Tier 4-5 (24〜25) は cleanup / 外部展開で daily efficiency への直接効果は小さい。

**Bundle 1 完了 (2026-04-29)**: 旧順位 3 (PowerShell swallowed error) + 旧順位 7 (Markdown 非 ASCII anchor) を `custom-lint-rules.toml` に追加して 1 PR で統合実装。詳細は git log 参照。**順位 19 (日付ベース見出しアンカー更新ルール) は決定論的防止 (旧順位 7 = `no-mutable-anchor` rule) との二重防衛として継続有効**。

**順位 8 (reviewer facet 改善) は全 PR の review 精度を即時向上させ、Tier 2 内で順位 7/9/10 と並列実施可能**。
**順位 11/12 (rate-limit 系の 2 タスク) は rate-limit 直撃のため Tier 2 内で最優先候補**。順位 11 = ポーリング頻度全体の削減、順位 12 = review 単位での自動再トリガー、順位 3 (Polling anti-pattern 検出) を含む 3 層で rate-limit を抑制する設計。
**順位 4 (Stop hook の lint:md 統合) は旧順位 1 (Markdown linter hook 統合、PR #88 で merged) の gap closure**。**順位 5 (AI 生成一時スクリプト pattern 検出) は現順位 1 (push 前 untracked `__*` hook、PR #85 T1-4) と関連** (実装前に擦り合わせ要)。
Comment thread
coderabbitai[bot] marked this conversation as resolved.
**順位 15 (`.failed` marker 自己文書化) は ADR-030 soft-fail 機構の運用負荷削減** (PR #89 セッションで recovery が機能した実証から派生、Effort S)。
**順位 19-22 (T3 グローバルルール 4 件) は `~/.claude/` 配下への XS 追記なので並列実施推奨**。
**順位 23 (採番管理簡素化 ADR) は本 table の cross-reference 維持コストを構造的に解消するメタタスク** (PR #88/#89/#90/Bundle 1 で連続して 30+ 箇所の renumber が発生し負債が顕在化)。

---

Expand Down
35 changes: 0 additions & 35 deletions docs/todo2.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,41 +479,6 @@ Phase 2 (任意、段階的緩和)

なし

### PowerShell `catch {}` swallowed error 検出 custom_lint_rule (PR #85 T1-2)

> **動機**: PR #85 のレビューで `__parse_transcripts.ps1:8` の `ConvertFrom-Json -ErrorAction SilentlyContinue` + 空 `catch {}` が CodeRabbit Major 指摘 (Review Policy 明示的 REJECT 項目「Swallowed errors」)。同種の swallowed error は Bash / TypeScript では既存の custom_lint_rule で検出可能だが、PowerShell は対象外だった。
>
> **本タスクの位置づけ**: ADR-007 (custom_lint_rule の正規表現/AST 層線引き) に従い、PowerShell スクリプトの空 `catch` ブロックと `-ErrorAction SilentlyContinue` を正規表現層で検出する。
>
> **参照**: `.claude/feedback-reports/85.md` Tier 1 #2
>
> **実行優先度**: 🚀 **Tier 1 (順位 3/26)** — XS 工数、ADR-007 既存基盤の拡張のみ。発生頻度は低いが該当時の影響大 (debug 困難化)。

#### 設計決定 (案)

- 配置先: `.claude/custom-lint-rules.toml` の `[powershell]` セクション (extensions: `["ps1"]`)
- 検出ルール:
- 空 `catch {}` ブロック (regex: `catch\s*\{\s*\}`)
- `-ErrorAction SilentlyContinue` (regex: `-ErrorAction\s+SilentlyContinue`)
- 同時検出を REJECT 扱い (片方単独は warning、組合せで error)

#### 作業計画

- [ ] `.claude/custom-lint-rules.toml` に PowerShell セクション追加
- [ ] PostToolUse hook の linter pipeline で `ps1` を統合
- [ ] dogfood: バックアップした `__parse_transcripts.ps1` で動作確認
- [ ] 派生プロジェクトへ deploy
- [ ] 本 todo2.md エントリを削除

#### 完了基準

- `.ps1` ファイル編集時に空 `catch {}` + SilentlyContinue が detect される
- 既存 swallowed error 0 件 (clean baseline)

#### 詰まっている箇所

なし

### `cli-pr-monitor` プロセス正常終了の integration test (PR #85 T2-2)

> **動機**: PR #85 の `pnpm create-pr` 完了後、`cli-pr-monitor.exe` がバックグラウンドで残留し手動 `taskkill` が必要だった。termination シグナル処理またはタイムアウトの問題の可能性があり、本セッションで初めて顕在化。回帰テストで継続的に検出できるようにする。
Expand Down
Loading