Skip to content

feat: 品質ツールの包括的な改善 - #555

Merged
keito4 merged 4 commits into
mainfrom
feat/comprehensive-quality-improvements
Mar 9, 2026
Merged

feat: 品質ツールの包括的な改善#555
keito4 merged 4 commits into
mainfrom
feat/comprehensive-quality-improvements

Conversation

@keito4

@keito4 keito4 commented Mar 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Hooks改善: リトライロジック追加、Biome競合検出
  • セキュリティスキャン強化: AI/プラットフォームキー検出パターン追加
  • ドキュメント修正: Git署名鍵設定を正しい形式に修正
  • テスト追加: BATS統合テスト、Python Hooksテスト
  • npm更新: 依存パッケージ更新

詳細

Hooks改善

  • pre_git_quality_gates.py にリトライロジックを追加
  • ネットワークエラー、一時的なファイルロック等に対する自動リトライ
  • Biome と ESLint/Prettier の同時使用を検出して警告表示

セキュリティスキャン強化

新たに検出可能なパターン:

  • AI: Anthropic, OpenAI, Gemini APIキー
  • Platform: Slack, Stripe, Supabase, Vercel, Linear
  • Generic: Bearer Token, Basic Auth

ドキュメント修正

SSH署名鍵の設定方法を修正:

  • Before: $(cat ~/.ssh/id_ed25519.pub) (内容を展開)
  • After: ~/.ssh/id_ed25519.pub (パスを直接使用)

テスト追加

  • test/integration/security-scripts.bats: セキュリティスクリプトの統合テスト
  • test/python/test_hooks.py: Python Hooks の基本テスト

Test plan

  • npm run format:check
  • npm run lint
  • npm test
  • Python hooks test (python3 test/python/test_hooks.py)
  • CI verification

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added retry/timeout handling for pre-commit quality checks with skip and retry behavior
    • Detects lint/format configuration conflicts (e.g., between Biome and ESLint/Prettier)
    • Expanded secret scanning to detect many AI, cloud, and platform keys and tokens; adjusted critical severity rules
  • Documentation

    • SSH signing key docs updated to reference the key file path instead of inline key contents
  • Tests

    • Added integration tests for security scripts and Python hook validation

## 変更内容

### Hooks改善
- pre_git_quality_gates.py にリトライロジックを追加
- ネットワークエラー・一時的エラーに対するリトライ機能
- Biome と ESLint/Prettier の競合検出警告を追加

### セキュリティスキャン強化
- AI サービスキー検出パターン追加(Anthropic, OpenAI, Gemini等)
- プラットフォームキー検出追加(Slack, Stripe, Supabase, Vercel, Linear等)
- Bearer Token, Basic Auth パターン追加
- 重大度判定の改善

### ドキュメント修正
- Git署名鍵設定を正しい形式に修正(ファイルパスを使用)
- README.md, SECURITY.md, credentials/README.md を更新

### テスト追加
- security-scripts.bats: セキュリティスクリプトの統合テスト
- test/python/test_hooks.py: Python Hooks の基本テスト

### その他
- npm パッケージ更新

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 9, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4adfb8b-e779-49ee-af46-af453e06e68d

📥 Commits

Reviewing files that changed from the base of the PR and between 29b75a7 and e8b3523.

📒 Files selected for processing (2)
  • .claude/hooks/pre_git_quality_gates.py
  • script/security-credential-scan.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • script/security-credential-scan.sh

📝 Walkthrough
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title uses Japanese and is vague/generic ('comprehensive quality improvements'), not clearly conveying the specific changes made despite being related to the changeset. Use a clear, concise English title that specifically describes the main changes, such as 'Add retry logic to quality gates, expand security scanning patterns, and fix SSH key configuration examples'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/comprehensive-quality-improvements

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@keito4

keito4 commented Mar 9, 2026

Copy link
Copy Markdown
Owner Author

🔍 AI Code Review (Local Hook)

Models: Codex (default) / Gemini (default)

🤖 Codex Review

指摘事項(重要度順)

  • パフォーマンス/DX: リトライが「タイムアウト」でも発生するため、1チェックあたり最大 timeout * (retries+1)(デフォルトで最大15分)までブロックされ得ます。従来は最大5分でした。CI/ローカルの品質ゲートが極端に遅くなる回帰です。.claude/hooks/pre_git_quality_gates.py:178-233
  • 保守性/正確性(誤検知増): Vercel Token の正規表現が「任意の24桁英数字」に一致し、通常のIDやハッシュを大量に誤検知します。警告件数・スコアを不必要に悪化させる回帰です。script/security-credential-scan.sh:100-105
  • 保守性/正確性(重複カウント): Gemini API KeyGoogle API Key と同一パターンのため、AIza... を二重に検出して警告件数を水増しします。script/security-credential-scan.sh:81-98

判定: patch is incorrect
理由: 品質ゲートの最大待ち時間が大幅に増える回帰と、セキュリティスキャンの誤検知/重複による信頼性低下が導入されています。
信頼度: 0.62

✨ Gemini Review

MCP server 'supabase' requires authentication using: /mcp auth supabaseMCP server 'vercel' requires authentication using: /mcp auth vercelレビューの結果、以下の問題点を指摘します。

指摘事項

  • ファイル: .claude/hooks/pre_git_quality_gates.py
  • 行範囲: 39, 48
  • 説明: detect_linter_conflicts 関数内で、linter/formatterの競合を検出するためのパッケージ名に不要な先頭スペースが含まれています (" @biomejs/biome", " @eslint/js")。package.json の依存関係は {"@biomejs/biome": "version"} のようにスペースなしで記録されるため、このままでは競合検出が正しく機能しません。先頭のスペースを削除してください。

全体的な正確性の判定

patch is incorrect

理由: 主要な新機能であるリンター競合検出ロジックに、パッケージ名のタイポという単純なバグが含まれており、この機能が意図通りに動作しません。リトライ処理の導入やドキュメントの改善は適切ですが、中核的な機能不全があるため、このパッチは不正確です。

信頼度: 1.0


⚠️ 修正が必要です

上記のレビューで問題が指摘されています。修正してからマージしてください。


🤖 Generated by post_pr_ai_review.py hook

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29b75a7584

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if [[ "$pattern_name" == *"AWS"* ]] || [[ "$pattern_name" == *"GitHub Token"* ]] || [[ "$pattern_name" == *"Private Key"* ]]; then
# Critical patterns: cloud credentials, API keys that provide full access
if [[ "$pattern_name" == *"AWS"* ]] || \
[[ "$pattern_name" == *"GitHub Token"* ]] || \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Treat new GitHub token patterns as CRITICAL

The strict-mode gate classifies only names matching *GitHub Token* as critical, so the newly added patterns (GitHub OAuth, GitHub App Token, GitHub Server-to-Server, GitHub Refresh Token) are downgraded to WARNING. In --strict runs this means leaked gho_/ghu_/ghs_/ghr_ credentials do not fail the scan (exit code stays 0), which weakens the commit/push protection this script is intended to enforce.

Useful? React with 👍 / 👎.

## 修正内容

### pre_git_quality_gates.py
- タイムアウト時のリトライを無効化(最大待ち時間の回帰を防止)
- タイムアウトは即座に失敗として扱う(5分→15分の待ち時間増加を回避)

### security-credential-scan.sh
- Gemini API Key パターンを削除(Google API Keyと重複)
- Vercel Token パターンを削除(24桁英数字は誤検知が多すぎる)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
.claude/hooks/pre_git_quality_gates.py (1)

17-20: Consider making timeout and retry settings configurable via environment variables.

The hardcoded values are reasonable defaults, but some environments may need longer timeouts (slow CI) or different retry strategies.

♻️ Optional: Environment variable overrides
 # 設定
-DEFAULT_TIMEOUT = 300  # 5分
-MAX_RETRIES = 2  # 最大リトライ回数
-RETRY_DELAY = 2  # リトライ間隔(秒)
+DEFAULT_TIMEOUT = int(os.environ.get("QUALITY_GATES_TIMEOUT", 300))  # 5分
+MAX_RETRIES = int(os.environ.get("QUALITY_GATES_MAX_RETRIES", 2))  # 最大リトライ回数
+RETRY_DELAY = int(os.environ.get("QUALITY_GATES_RETRY_DELAY", 2))  # リトライ間隔(秒)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/pre_git_quality_gates.py around lines 17 - 20, Replace
hardcoded DEFAULT_TIMEOUT, MAX_RETRIES, and RETRY_DELAY with values read from
environment variables (e.g., CLAUDE_TIMEOUT, CLAUDE_MAX_RETRIES,
CLAUDE_RETRY_DELAY) while preserving the current defaults; in the module where
DEFAULT_TIMEOUT, MAX_RETRIES, and RETRY_DELAY are defined, read os.environ.get
for each, attempt safe int conversion with fallback to the existing constants,
and handle invalid values by falling back and optionally logging a warning;
ensure any code using DEFAULT_TIMEOUT, MAX_RETRIES, and RETRY_DELAY continues to
reference these symbols so behavior is unchanged when env vars are absent.
script/security-credential-scan.sh (1)

103-103: Supabase Key pattern matches generic JWTs.

The pattern eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\\. matches the standard JWT header for HS256 tokens, which is used by many services beyond Supabase. This may generate findings labeled "Supabase Key" for unrelated JWTs.

Consider renaming to "JWT (HS256)" or adding context-based detection (e.g., checking for supabase in the surrounding text).

♻️ Suggested: Rename for accuracy
-PATTERNS["Supabase Key"]="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+"
+# Generic HS256 JWT - commonly used by Supabase, Auth0, and other services
+PATTERNS["JWT Token (HS256)"]="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+"

Note: You already have a generic "JWT Token" pattern on line 110. Consider whether both are needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@script/security-credential-scan.sh` at line 103, The "Supabase Key" regex
stored in PATTERNS["Supabase Key"] is too generic (it just matches HS256 JWT
headers) so update detection to avoid false positives: either rename the key to
"JWT (HS256)" or enhance the pattern to require Supabase context (e.g.,
lookaround or require the word "supabase" near the token), and if you keep both
patterns reconcile with the existing "JWT Token" entry (remove or differentiate
one) so you don't duplicate generic JWT detection; update PATTERNS["Supabase
Key"] accordingly and adjust any tests or references that rely on that key name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/hooks/pre_git_quality_gates.py:
- Around line 158-175: The function is_retryable_error currently declares an
unused returncode parameter; remove that parameter from the function signature
(change def is_retryable_error(stderr: str) -> bool) and update every call site
that passes a return code to instead call is_retryable_error(stderr) so the
function only inspects stderr; ensure you update import/type hints if any and
run tests to confirm all callers compile.

In `@script/security-credential-scan.sh`:
- Line 97: PATTERNS["Gemini API Key"] duplicates PATTERNS["Google API Key"]
(both use `AIza[0-9A-Za-z\\-_]{35}`); remove the duplicate entry or consolidate
it under the Google pattern by deleting the PATTERNS["Gemini API Key"] line, or
if you must keep a separate Gemini entry, replace the Gemini regex with the
correct distinctive pattern or add a clear comment above PATTERNS["Gemini API
Key"] indicating it intentionally reuses the Google regex to avoid duplicate
findings; update any test cases or documentation referencing the Gemini key
accordingly.
- Line 104: The PATTERNS["Vercel Token"] entry is too generic and causes false
positives; update the PATTERNS["Vercel Token"] regex to a stricter form (for
example require a known prefix like "vercel_" or other canonical Vercel token
structure) or remove the pattern and add a comment documenting the limitation;
change the value assigned to PATTERNS["Vercel Token"] (noting the symbol name in
the diff) to a tighter regex that includes the prefix and appropriate
length/charset, or delete the entry and add a brief comment explaining why a
reliable regex could not be determined.

In `@test/integration/security-scripts.bats`:
- Around line 65-66: The test currently writes a literal-looking AWS key into
the repo (echo 'const key = "AKIAIOSFODNN7EXAMPLE";' > "$temp_dir/test.js"),
which triggers the credential scanner; instead, compose the fake key at runtime
from non-matching fragments (e.g. concatenate prefix "AKIA" with other
substrings) and write that assembled string into "$temp_dir/test.js" so no
literal AKIA... token appears in source; apply the same change to the other
occurrence around lines 77-78 in the same test file and ensure the assembled key
still matches the intended test value when evaluated by the test harness.

In `@test/python/test_hooks.py`:
- Around line 33-45: The test currently just greps text in test_hooks.py and
must be replaced with real verification: parse pre_git_quality_gates.py with the
AST module to assert the presence of real top-level function definitions (e.g.,
detect_package_manager, has_biome, get_package_scripts, run_with_retry,
detect_linter_conflicts) rather than string matches, and add behavioral unit
tests that import the module and execute the new logic paths for run_with_retry
and detect_linter_conflicts (mocking/simulating failures and conflicting linter
configs) to ensure retry behavior and conflict detection run as expected; update
test names and assertions to validate actual API signatures and outcomes instead
of text presence.

---

Nitpick comments:
In @.claude/hooks/pre_git_quality_gates.py:
- Around line 17-20: Replace hardcoded DEFAULT_TIMEOUT, MAX_RETRIES, and
RETRY_DELAY with values read from environment variables (e.g., CLAUDE_TIMEOUT,
CLAUDE_MAX_RETRIES, CLAUDE_RETRY_DELAY) while preserving the current defaults;
in the module where DEFAULT_TIMEOUT, MAX_RETRIES, and RETRY_DELAY are defined,
read os.environ.get for each, attempt safe int conversion with fallback to the
existing constants, and handle invalid values by falling back and optionally
logging a warning; ensure any code using DEFAULT_TIMEOUT, MAX_RETRIES, and
RETRY_DELAY continues to reference these symbols so behavior is unchanged when
env vars are absent.

In `@script/security-credential-scan.sh`:
- Line 103: The "Supabase Key" regex stored in PATTERNS["Supabase Key"] is too
generic (it just matches HS256 JWT headers) so update detection to avoid false
positives: either rename the key to "JWT (HS256)" or enhance the pattern to
require Supabase context (e.g., lookaround or require the word "supabase" near
the token), and if you keep both patterns reconcile with the existing "JWT
Token" entry (remove or differentiate one) so you don't duplicate generic JWT
detection; update PATTERNS["Supabase Key"] accordingly and adjust any tests or
references that rely on that key name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: de71a8d9-8a2e-4a02-a4db-42710adbe024

📥 Commits

Reviewing files that changed from the base of the PR and between d75623b and 29b75a7.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • .claude/hooks/pre_git_quality_gates.py
  • README.md
  • SECURITY.md
  • credentials/README.md
  • git/gitconfig
  • script/import.sh
  • script/lib/config.sh
  • script/security-credential-scan.sh
  • test/integration/security-scripts.bats
  • test/python/test_hooks.py

Comment on lines +158 to +175
def is_retryable_error(returncode: int, stderr: str) -> bool:
"""リトライ可能なエラーかどうか判定"""
# ネットワーク系エラー
network_errors = [
"ECONNREFUSED",
"ETIMEDOUT",
"ENOTFOUND",
"network error",
"socket hang up",
"EAI_AGAIN",
]
for err in network_errors:
if err in stderr:
return True
# 一時的なファイルロック
if "EBUSY" in stderr or "resource busy" in stderr.lower():
return True
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Unused returncode parameter.

The returncode parameter is declared but never used in the function body. The current implementation only checks stderr content for retryable error patterns.

Consider either removing the parameter or using it to identify additional retryable conditions (e.g., specific exit codes that indicate transient failures).

🔧 Option 1: Remove unused parameter
-def is_retryable_error(returncode: int, stderr: str) -> bool:
+def is_retryable_error(stderr: str) -> bool:
     """リトライ可能なエラーかどうか判定"""

Then update the call site at line 205-206:

-            if attempt < max_retries and is_retryable_error(
-                result.returncode, result.stderr
-            ):
+            if attempt < max_retries and is_retryable_error(result.stderr):
🔧 Option 2: Use returncode for additional checks
 def is_retryable_error(returncode: int, stderr: str) -> bool:
     """リトライ可能なエラーかどうか判定"""
+    # Transient exit codes (e.g., signal interrupts)
+    if returncode in (130, 137, 143):  # SIGINT, SIGKILL, SIGTERM
+        return True
+
     # ネットワーク系エラー
     network_errors = [
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def is_retryable_error(returncode: int, stderr: str) -> bool:
"""リトライ可能なエラーかどうか判定"""
# ネットワーク系エラー
network_errors = [
"ECONNREFUSED",
"ETIMEDOUT",
"ENOTFOUND",
"network error",
"socket hang up",
"EAI_AGAIN",
]
for err in network_errors:
if err in stderr:
return True
# 一時的なファイルロック
if "EBUSY" in stderr or "resource busy" in stderr.lower():
return True
return False
def is_retryable_error(returncode: int, stderr: str) -> bool:
"""リトライ可能なエラーかどうか判定"""
# Transient exit codes (e.g., signal interrupts)
if returncode in (130, 137, 143): # SIGINT, SIGKILL, SIGTERM
return True
# ネットワーク系エラー
network_errors = [
"ECONNREFUSED",
"ETIMEDOUT",
"ENOTFOUND",
"network error",
"socket hang up",
"EAI_AGAIN",
]
for err in network_errors:
if err in stderr:
return True
# 一時的なファイルロック
if "EBUSY" in stderr or "resource busy" in stderr.lower():
return True
return False
🧰 Tools
🪛 Ruff (0.15.4)

[warning] 158-158: Unused function argument: returncode

(ARG001)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/pre_git_quality_gates.py around lines 158 - 175, The function
is_retryable_error currently declares an unused returncode parameter; remove
that parameter from the function signature (change def
is_retryable_error(stderr: str) -> bool) and update every call site that passes
a return code to instead call is_retryable_error(stderr) so the function only
inspects stderr; ensure you update import/type hints if any and run tests to
confirm all callers compile.

Comment thread script/security-credential-scan.sh Outdated
Comment thread script/security-credential-scan.sh Outdated
Comment on lines +65 to +66
# Create file with fake AWS key pattern
echo 'const key = "AKIAIOSFODNN7EXAMPLE";' > "$temp_dir/test.js"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid committing a literal AWS-looking key in the test source.

script/security-credential-scan.sh matches AKIA[0-9A-Z]{16} and classifies AWS hits as CRITICAL, so these checked-in literals make the repository fail its own credential scan when the repo is scanned. Build the fake key from split fragments at runtime instead.

Suggested fix
-    echo 'const key = "AKIAIOSFODNN7EXAMPLE";' > "$temp_dir/test.js"
+    fake_aws_key='AKIA'"IOSFODNN7EXAMPLE"
+    printf 'const key = "%s";\n' "$fake_aws_key" > "$temp_dir/test.js"
-    echo 'const key = "AKIAIOSFODNN7EXAMPLE";' > "$temp_dir/test.js"
+    fake_aws_key='AKIA'"IOSFODNN7EXAMPLE"
+    printf 'const key = "%s";\n' "$fake_aws_key" > "$temp_dir/test.js"

Also applies to: 77-78

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/security-scripts.bats` around lines 65 - 66, The test
currently writes a literal-looking AWS key into the repo (echo 'const key =
"AKIAIOSFODNN7EXAMPLE";' > "$temp_dir/test.js"), which triggers the credential
scanner; instead, compose the fake key at runtime from non-matching fragments
(e.g. concatenate prefix "AKIA" with other substrings) and write that assembled
string into "$temp_dir/test.js" so no literal AKIA... token appears in source;
apply the same change to the other occurrence around lines 77-78 in the same
test file and ensure the assembled key still matches the intended test value
when evaluated by the test harness.

Comment thread test/python/test_hooks.py
Comment on lines +33 to +45
content = hook_file.read_text()

required_functions = [
"detect_package_manager",
"has_biome",
"get_package_scripts",
"run_with_retry",
"detect_linter_conflicts",
]

for func in required_functions:
assert f"def {func}" in content, \
f"Missing function: {func} in pre_git_quality_gates.py"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

This only greps source text; it doesn't verify the hook API or behavior.

A comment or string containing def run_with_retry would satisfy this test, and none of the new retry/conflict paths are executed. Parse the module AST for real top-level definitions, then add behavioral tests for the newly added logic.

Suggested fix
+import ast
+
 ...
-    content = hook_file.read_text()
+    tree = ast.parse(hook_file.read_text(encoding="utf-8"))
+    defined_functions = {
+        node.name for node in tree.body if isinstance(node, ast.FunctionDef)
+    }

     required_functions = [
         "detect_package_manager",
         "has_biome",
         "get_package_scripts",
         "run_with_retry",
         "detect_linter_conflicts",
     ]

     for func in required_functions:
-        assert f"def {func}" in content, \
+        assert func in defined_functions, \
             f"Missing function: {func} in pre_git_quality_gates.py"

As per coding guidelines, "Follow TDD methodology: Red → Green → Refactor with minimum 70% line code coverage".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/python/test_hooks.py` around lines 33 - 45, The test currently just
greps text in test_hooks.py and must be replaced with real verification: parse
pre_git_quality_gates.py with the AST module to assert the presence of real
top-level function definitions (e.g., detect_package_manager, has_biome,
get_package_scripts, run_with_retry, detect_linter_conflicts) rather than string
matches, and add behavioral unit tests that import the module and execute the
new logic paths for run_with_retry and detect_linter_conflicts
(mocking/simulating failures and conflicting linter configs) to ensure retry
behavior and conflict detection run as expected; update test names and
assertions to validate actual API signatures and outcomes instead of text
presence.

keito4 and others added 2 commits March 9, 2026 18:28
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@claude

claude Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

PR レビュー: feat: 品質ツールの包括的な改善

全体的によくまとまった改善です。各変更について詳細なフィードバックをまとめます。


✅ 良い点

  • ドキュメント修正(SSH署名鍵): $(cat ~/.ssh/id_ed25519.pub)~/.ssh/id_ed25519.pub は正しい修正です。gpg.format = ssh の場合、signingkey はファイルパスを期待するため、内容を展開してしまうと動作しません。
  • run_with_retry: ネットワーク/ロックエラーのみをリトライ対象に限定しており、CIを恣意的に通過させるような乱用は防げています。
  • リトライ除外設計: タイムアウトはリトライしない(長時間ブロック防止)という設計判断が適切です。
  • セキュリティスキャン強化: AI系キー(OpenAI/Anthropic)、Platform系(Slack/Stripe/Supabase/Linear)の追加は現実的なリスクカバレッジ向上です。
  • .claude ディレクトリの除外: EXCLUDE_DIRS.claude が追加されており、hooks自体がスキャン対象になるのを防いでいます。

🔴 要修正: バグ・誤検知リスク

1. detect_linter_conflicts の誤検知 — eslint-config-prettier

ファイル: .claude/hooks/pre_git_quality_gates.py

eslint-config-prettier は ESLint と Prettier の 競合を解消するための 互換レイヤーであり、Biome との競合指標としては不適切です。むしろ「ESLint + Prettier を共存させている」証拠であり、Biome 移行の余地があることを示しますが、警告内容が誤解を招きます。

提案: eslint-config-prettier をリストから除外するか、専用のメッセージに変更する。


2. AWS Secret パターンの高い誤検知率

ファイル: script/security-credential-scan.sh

PATTERNS["AWS Secret"]="['\"][A-Za-z0-9/+=]{40}['\"]"

40文字のBase64文字列を含む任意の文字列がヒットします。チェックサム、ハッシュ、エンコードされた値など、通常のコードで頻繁に出現します。

提案: このパターンは警告レベルに留めるか、AWS固有のコンテキスト(変数名など)を組み合わせて精度を高める。


3. Supabase KeyJWT Token パターンの重複アラート

ファイル: script/security-credential-scan.sh

Supabase の JWT は汎用の JWT パターンにもヒットするため、同一の値が2回検出されます。

提案: 重複排除ロジックを追加するか、パターンを統合する。


🟡 改善推奨

4. Pythonテストがテストランナーに統合されていない

ファイル: test/python/test_hooks.py

現在は python3 test/python/test_hooks.py で直接実行する形式で、npm test / Jest には統合されていません。CI での自動実行対象に含まれない可能性があります。

提案: package.jsonscripts に追加する。例:"test:hooks": "python3 test/python/test_hooks.py"


5. BATSテストの依存関係確認

ファイル: test/integration/security-scripts.bats

load ../test_helper/test_helperbats-support / bats-assert が必要ですが、リポジトリへの含まれ方やインストール手順が PR に記載されていません。CI ワークフローでの動作確認を確認してください。


6. Bearer Token / Basic Auth パターンの誤検知可能性

ファイル: script/security-credential-scan.sh

.md は除外済みですが、テストフィクスチャやシェルスクリプトのコメント等で誤検知する可能性があります。現状 WARNING 扱いであれば許容できますが、EXCLUDE_PATTERNS の拡充を検討してください。


📋 その他

  • script/import.shscript/lib/config.sh の1行変更が PR 説明に記載されていません。内容を確認してください。
  • package-lock.json の大量削除(-1341行)は依存関係の重複排除によるものであり、問題ありません。

総評

コアロジックの改善(リトライ、競合検出)は価値があります。要修正 の点(特に eslint-config-prettier の誤分類と AWS Secret パターンの精度)を対応いただけると、誤検知によるユーザー体験の低下を防げます。テスト統合についても CI での自動実行を確認してください。

🤖 Reviewed with Claude Code

@keito4
keito4 merged commit d06afa5 into main Mar 9, 2026
16 checks passed
@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.93.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released リリース済み

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant