Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions .claude/skills/create-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ description: GitHub PR作成コマンド

## 注意事項

- ベースブランチは通常 `develop` ですが、確認してください
- PR 本文には必ず PR-Agent のコマンドを含めてください
- 必要に応じて、複数のコミットに分けることも検討してください
- ベースブランチは通常 `develop` ですが、確認してください
- PR 本文には必ず PR-Agent のコマンドを含めてください
- 必要に応じて、複数のコミットに分けることも検討してください
86 changes: 43 additions & 43 deletions .claude/skills/review-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Github MCP を用いて PR の内容を取得し、品質憲章や各種ガイ

## 必須引数

- `$PR_URL`: Github Pull Request URL (例: <https://github.com/offich/sangria/pull/1>)
- `$PR_URL`: Github Pull Request URL (例: <https://github.com/offich/sangria/pull/1>)

## 動作フロー

Expand All @@ -23,54 +23,54 @@ Github MCP を用いて PR の内容を取得し、品質憲章や各種ガイ

### 🔍 基本チェック項目

- **命名規則の遵守**
- 変数・関数・クラス名が意図を明確に表現しているか
- **命名規則の遵守**
- 変数・関数・クラス名が意図を明確に表現しているか
<!-- - ユビキタス言語を使用しているか -->
- 日本語のローマ字変換を避けているか

- **CLEANなコード**
- 凝集度(Cohesion)が高いか
- 疎結合(Loose Coupling)になっているか
- 適切にカプセル化されているか
- 抽象化のレベルが適切か
- 冗長性がないか(DRY原則)
- **関数・クラス設計**
- 単一責任の原則を守っているか
- 引数の数が適切か
- フラグ引数を使っていないか
- 日本語のローマ字変換を避けているか

- **CLEANなコード**
- 凝集度(Cohesion)が高いか
- 疎結合(Loose Coupling)になっているか
- 適切にカプセル化されているか
- 抽象化のレベルが適切か
- 冗長性がないか(DRY原則)
- **関数・クラス設計**
- 単一責任の原則を守っているか
- 引数の数が適切か
- フラグ引数を使っていないか

### 📝 コメント・ドキュメント

- コメントよりコードで表現されているか
- 必要なコメントは背景・理由を説明しているか
- テーブル・カラムにコメントが記載されているか
- コメントよりコードで表現されているか
- 必要なコメントは背景・理由を説明しているか
- テーブル・カラムにコメントが記載されているか

### 🧪 テスト

- テストコードが追加・修正されているか
- F.I.R.S.Tなテストになっているか
- Fast(高速)
- Independent(独立)
- Repeatable(再現性)
- Self-Validating(自己検証)
- Timely(適時性)
- テストコードが追加・修正されているか
- F.I.R.S.Tなテストになっているか
- Fast(高速)
- Independent(独立)
- Repeatable(再現性)
- Self-Validating(自己検証)
- Timely(適時性)

## プロダクト構成とドキュメント

PR の diff 箇所に合わせて、下記を参照してください。

### 📋 ガイドライン

- **レビューガイドライン**: `docs/dev/review-guideline.md`
- **レビューガイドライン**: `docs/dev/review-guideline.md`

## レビューお作法

- Github MCPを通じてレビューを行うこと
- `mcp__github__pull_request_review_write` で pending review を作成
- `mcp__github__add_comment_to_pending_review` を用いてファイル、行指定で該当箇所にコメントを入れていくこと
- 一通りのコメントを終えたタイミングで、 `submit_pending_pull_request_review` を用いてレビュー送信すること
- すでにインラインでPR作成車によってコメントがされている箇所がある場合、そのコメントに対して反応すること
- いずれの場合も、「Claude Code によるコメント」である旨を明記すること
- Github MCPを通じてレビューを行うこと
- `mcp__github__pull_request_review_write` で pending review を作成
- `mcp__github__add_comment_to_pending_review` を用いてファイル、行指定で該当箇所にコメントを入れていくこと
- 一通りのコメントを終えたタイミングで、 `submit_pending_pull_request_review` を用いてレビュー送信すること
- すでにインラインでPR作成車によってコメントがされている箇所がある場合、そのコメントに対して反応すること
- いずれの場合も、「Claude Code によるコメント」である旨を明記すること

### `submit_pending_pull_request_review` 時のテンプレート

Expand All @@ -94,10 +94,10 @@ PR の diff 箇所に合わせて、下記を参照してください。

## エラーハンドリング

- **PR が存在しない場合**: エラーメッセージを表示し、PR番号の確認を促す
- **アクセス権限がない場合**: 権限設定の確認を促す
- **ネットワークエラー**: リトライまたは手動でのレビューを促す
- **差分が大きすぎる場合**: 重要な変更に絞ってレビューを実施
- **PR が存在しない場合**: エラーメッセージを表示し、PR番号の確認を促す
- **アクセス権限がない場合**: 権限設定の確認を促す
- **ネットワークエラー**: リトライまたは手動でのレビューを促す
- **差分が大きすぎる場合**: 重要な変更に絞ってレビューを実施

## 使用例

Expand All @@ -107,13 +107,13 @@ PR の diff 箇所に合わせて、下記を参照してください。
/review:review-pr https://github.com/offich/sangria/pull/10
```

- PRの変更内容を取得
- コーディングガイドラインに基づいてレビュー
- 改善点をGitHubにコメント投稿
- PRの変更内容を取得
- コーディングガイドラインに基づいてレビュー
- 改善点をGitHubにコメント投稿

## 注意事項

- レビューは自動生成の提案であり、最終的な判断は人間が行うこと
- ビジネスロジックの妥当性は判断できないため、技術的な観点のみレビュー
- 大規模なPRの場合、重要度の高い指摘に絞ってコメント
- 既存コードのスタイルに合わせることを優先
- レビューは自動生成の提案であり、最終的な判断は人間が行うこと
- ビジネスロジックの妥当性は判断できないため、技術的な観点のみレビュー
- 大規模なPRの場合、重要度の高い指摘に絞ってコメント
- 既存コードのスタイルに合わせることを優先
51 changes: 51 additions & 0 deletions .github/workflows/docs-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: 'docs-analysis'

on:
push:
paths:
- 'CHANGELOG.md'
- '.claude/**/*.md'
- 'docs/**/*.md'
- 'package.json'
- 'pnpm-lock.yaml'
- '.markdownlint-cli2.yaml'
- '.github/workflows/docs-analysis.yml'

branches-ignore:
- release

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint-markdown:
runs-on: ubuntu-24.04
timeout-minutes: 10

steps:
- name: checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1

- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1

- uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0

- name: get pnpm store path
id: pnpm-store
run: echo "path=$(pnpm store path)" >> $GITHUB_OUTPUT

- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
id: pnpm-cache
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}

- name: install dependencies
if: steps.pnpm-cache.outputs.cache-hit != 'true'
run: pnpm install

- name: lint markdown
run: pnpm run lint:markdown
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ build/
.fvm/

.mcp.json

node_modules
3 changes: 3 additions & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
config:
MD013:
code_blocks: false
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Changelog

## 0.3.0

* Add the following lint:
Expand Down
136 changes: 69 additions & 67 deletions docs/dev/review-guideline.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

DevTools Extension のコードをレビューし、以下の観点で指摘してください。

- `Effective Dart のベストプラクティス遵守`
- `バグやクラッシュにつながる可能性`
- `VM Service / DTD との通信パターンの正確性`
- `非同期処理の危険パターン`
- `アイソレート変化・ホットリロードへの対応`
- `Effective Dart のベストプラクティス遵守`
- `バグやクラッシュにつながる可能性`
- `VM Service / DTD との通信パターンの正確性`
- `非同期処理の危険パターン`
- `アイソレート変化・ホットリロードへの対応`

特に **致命的バグパターン** の検出を最優先設定。DevTools 内でクラッシュ・フリーズ・データ化け・メモリリークを引き起こす可能性のある問題を重点的にチェックしてください。

Expand All @@ -26,101 +26,103 @@ DevTools Extension は Flutter **Web** アプリとして iFrame 内で動作し

### VM Service / DTD 通信

- [ ] **サービス呼び出しのエラーハンドリング**
- [ ] `serviceManager.callServiceExtension()` に `try-catch` / `.catchError()` があるか
- [ ] 切断中・未接続時に呼び出しが発生しないよう `isServiceAvailable` を確認しているか
- [ ] タイムアウトが設定されており、長時間ブロックしないか
- [ ] **サービス拡張のレスポンス**
- [ ] ハンドラが必ず `ServiceExtensionResponse.result()` または `.error()` を返すか
- [ ] Future が複数回完了する(ホットリスタート時の二重完了)パターンがないか
- [ ] パラメータの JSON デコードで例外が起きてもクラッシュしないか
- [ ] **DTD 利用**
- [ ] `dtdManager` が利用不可の場合に適切にフォールバックしているか
- [ ] ファイル操作が DTD 経由になっているか(直接 `dart:io` は使えない)
- [ ] **サービス呼び出しのエラーハンドリング**
- [ ] `serviceManager.callServiceExtension()` に
`try-catch` / `.catchError()` があるか
- [ ] 切断中・未接続時に呼び出しが発生しないよう `isServiceAvailable` を確認しているか
- [ ] タイムアウトが設定されており、長時間ブロックしないか
- [ ] **サービス拡張のレスポンス**
- [ ] ハンドラが必ず `ServiceExtensionResponse.result()` または `.error()` を返すか
- [ ] Future が複数回完了する(ホットリスタート時の二重完了)パターンがないか
- [ ] パラメータの JSON デコードで例外が起きてもクラッシュしないか
- [ ] **DTD 利用**
- [ ] `dtdManager` が利用不可の場合に適切にフォールバックしているか
- [ ] ファイル操作が DTD 経由になっているか(直接 `dart:io` は使えない)

### アイソレート変化・ホットリロード

- [ ] **古いアイソレート参照**
- [ ] アイソレート変化時にリスナーを再登録しているか
- [ ] `selectedIsolate` の変化を `addListener` で監視し、処理を切り替えているか
- [ ] **ストリームの再購読**
- [ ] ホットリロード後にストリームが無効化されていないか
- [ ] `initState` で購読し `dispose` でキャンセルしているか
- [ ] **古いアイソレート参照**
- [ ] アイソレート変化時にリスナーを再登録しているか
- [ ] `selectedIsolate` の変化を `addListener` で監視し、処理を切り替えているか
- [ ] **ストリームの再購読**
- [ ] ホットリロード後にストリームが無効化されていないか
- [ ] `initState` で購読し `dispose` でキャンセルしているか

### リスナー・サブスクリプションのリーク

- [ ] **dispose 漏れ**
- [ ] `serviceManager` / `extensionManager` / `dtdManager` へのリスナーが `dispose()` でキャンセルされているか
- [ ] `StreamSubscription` が未キャンセルで放置されていないか
- [ ] タイマー・ポーリングが Extension タブを閉じると停止するか
- [ ] **dispose 漏れ**
- [ ] `serviceManager` / `extensionManager` / `dtdManager`
へのリスナーが `dispose()` でキャンセルされているか
- [ ] `StreamSubscription` が未キャンセルで放置されていないか
- [ ] タイマー・ポーリングが Extension タブを閉じると停止するか

### 接続状態管理

- [ ] **未接続時の動作**
- [ ] `requiresConnection: true` の場合、未接続でサービス呼び出しを行っていないか
- [ ] 接続・切断イベントで UI 状態が正しく更新されるか
- [ ] **非同期処理中の切断**
- [ ] 長時間の処理中に切断が発生した場合にハンドリングされているか
- [ ] **未接続時の動作**
- [ ] `requiresConnection: true` の場合、未接続でサービス呼び出しを行っていないか
- [ ] 接続・切断イベントで UI 状態が正しく更新されるか
- [ ] **非同期処理中の切断**
- [ ] 長時間の処理中に切断が発生した場合にハンドリングされているか

### 非同期処理の一般的な危険パターン

- [ ] **unawaited Future**
- [ ] `initState` や `afterBuild` で `await` 漏れがないか
- [ ] 例外がサイレントに握りつぶされていないか
- [ ] **並行処理の管理**
- [ ] 複数の `callServiceExtension` を直列で呼ぶ必要があるとき、順序保証されているか
- [ ] `Future.wait` で一件失敗時に残りの処理が中断されないか
- [ ] **unawaited Future**
- [ ] `initState` や `afterBuild` で `await` 漏れがないか
- [ ] 例外がサイレントに握りつぶされていないか
- [ ] **並行処理の管理**
- [ ] 複数の `callServiceExtension` を直列で呼ぶ必要があるとき、順序保証されているか
- [ ] `Future.wait` で一件失敗時に残りの処理が中断されないか

---

### 一般的なコード品質

- [ ] 可読性・保守性
- [ ] 設計原理の遵守
- [ ] **null 安全・型安全**
- [ ] サービスレスポンスの JSON パースで null クラッシュがないか
- [ ] `serviceManager` / `dtdManager` が null のまま使われていないか
- [ ] テスト可能性
- [ ] セキュリティ(サービス拡張のパラメータバリデーション)
- [ ] 可読性・保守性
- [ ] 設計原理の遵守
- [ ] **null 安全・型安全**
- [ ] サービスレスポンスの JSON パースで null クラッシュがないか
- [ ] `serviceManager` / `dtdManager` が null のまま使われていないか
- [ ] テスト可能性
- [ ] セキュリティ(サービス拡張のパラメータバリデーション)

### プロジェクト固有

- [ ] 命名規則の統一
- [ ] サービス拡張のメソッド名が `ext.<packageName>.<methodName>` 形式か
- [ ] `config.yaml` に必須フィールド(`name`, `version`, `issueTracker`, `materialIconCodePoint`)があるか
- [ ] `DevToolsExtension` ウィジェットがルートに配置されているか
- [ ] 既存コードの整合性
- [ ] 命名規則の統一
- [ ] サービス拡張のメソッド名が `ext.<packageName>.<methodName>` 形式か
- [ ] `config.yaml` に必須フィールド(`name`, `version`, `issueTracker`, `materialIconCodePoint`)があるか
- [ ] `DevToolsExtension` ウィジェットがルートに配置されているか
- [ ] 既存コードの整合性

---

## レビューで出力される内容

### 1. **致命的問題の指摘**

- クラッシュ・フリーズ・メモリリークの可能性
- VM Service / DTD の不正な使用
- データ損失リスク(アイソレート変化時の状態喪失など)
- セキュリティ上の問題
- クラッシュ・フリーズ・メモリリークの可能性
- VM Service / DTD の不正な使用
- データ損失リスク(アイソレート変化時の状態喪失など)
- セキュリティ上の問題

### 2. **致命的バグ・クラッシュの検出パターン**

- **dispose 漏れ**: タブを閉じてもリスナーが残り続けメモリを消費
- **二重完了 Future**: ホットリスタートでハンドラが二度呼ばれ例外
- **古いアイソレート参照**: ホットリロード後に無効なアイソレートへアクセス
- **切断中のサービス呼び出し**: 切断後に `callServiceExtension` してクラッシュ
- **unawaited Future**: 例外が握りつぶされてサイレント失敗
- **JSON パースクラッシュ**: 不正なパラメータで `jsonDecode` が例外
- **dispose 漏れ**: タブを閉じてもリスナーが残り続けメモリを消費
- **二重完了 Future**: ホットリスタートでハンドラが二度呼ばれ例外
- **古いアイソレート参照**: ホットリロード後に無効なアイソレートへアクセス
- **切断中のサービス呼び出し**: 切断後に `callServiceExtension` してクラッシュ
- **unawaited Future**: 例外が握りつぶされてサイレント失敗
- **JSON パースクラッシュ**: 不正なパラメータで `jsonDecode` が例外

### 3. **改善提案**

- より堅牢な実装方法
- 適切な例外処理パターン
- エラー回復戦略の提案
- より堅牢な実装方法
- 適切な例外処理パターン
- エラー回復戦略の提案

### 4. **具体的修正コード例**

- 修正前後のコード比較
- 推奨実装パターン
- 修正前後のコード比較
- 推奨実装パターン

---

Expand Down Expand Up @@ -243,6 +245,6 @@ Future<ServiceExtensionResponse> handler(String method, Map<String, String> para

## オプション

- `--pre-commit` : コミット前チェックモード(より厳密なレビュー)
- `--focus=performance` : 特定の観点に絞ったレビュー
- `--japanese` : 日本語でのレビュー結果出力
- `--pre-commit` : コミット前チェックモード(より厳密なレビュー)
- `--focus=performance` : 特定の観点に絞ったレビュー
- `--japanese` : 日本語でのレビュー結果出力
Loading