Skip to content

feat: Harness Engineering Hooks を追加(自動リント・設定保護・完了前テスト) - #602

Merged
keito4 merged 1 commit into
mainfrom
feat/harness-engineering-hooks
Mar 21, 2026
Merged

feat: Harness Engineering Hooks を追加(自動リント・設定保護・完了前テスト)#602
keito4 merged 1 commit into
mainfrom
feat/harness-engineering-hooks

Conversation

@keito4

@keito4 keito4 commented Mar 21, 2026

Copy link
Copy Markdown
Owner

Summary

Harness Engineering ベストプラクティス から3つの Hook パターンを導入:

1. post_edit_auto_lint.py — PostToolUse 自動リント

  • ファイル編集後に自動フォーマット + リントを即座に実行
  • 残った違反を additionalContext として返し、エージェントの自己修正ループを駆動
  • 対応言語: TS/JS (biome/oxlint), Python (ruff), Shell (shellcheck)

2. block_config_edit.py — PreToolUse 設定保護

  • リンター/フォーマッター設定ファイル(eslint, biome, prettier, tsconfig, ruff 等)の編集をブロック
  • エージェントが設定を緩和してテストをパスさせることを防止
  • 「コードを修正せよ、リンター設定を変更するな」原則

3. stop_test_verification.py — Stop テスト検証

  • エージェント完了前にテストスイートを自動実行
  • テスト失敗時はフィードバックを返し修正を促す
  • 無限ループ防止(STOP_HOOK_ACTIVE)、Git 変更なし時はスキップ

設定

  • .claude/settings.json(ローカル)と .devcontainer/claude-settings.json(DevContainer)の両方に登録済み
  • config-base イメージ経由で全 DevContainer/Codespaces 環境にデフォルト適用

Test plan

  • block_config_edit.py: 保護対象ファイル → exit 2 でブロック確認
  • block_config_edit.py: 通常ファイル → パス確認
  • post_edit_auto_lint.py: JS ファイル → oxlint 実行確認
  • post_edit_auto_lint.py: 非対象ファイル → スキップ確認
  • post_edit_auto_lint.py: 0 errors/warnings → 出力なし確認
  • 設定ファイル JSON 構文検証(settings.json, claude-settings.json)
  • 全テストスイート Pass

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Linter and formatter configuration files are now protected from direct edits during agent operations
    • Automatic code formatting, linting, and diagnostics reporting runs after file modifications with built-in self-correction
    • Automated test verification executes before session completion, with failure diagnostics and reporting
  • Documentation

    • Updated hook documentation describing new automated capabilities and execution triggers

3つの新しい Claude Code Hooks を追加:

1. post_edit_auto_lint.py (PostToolUse)
   - ファイル編集後に自動フォーマット + リントを実行
   - 残った違反を additionalContext で返しエージェントの自己修正を促す
   - 対応: TS/JS (biome/oxlint), Python (ruff), Shell (shellcheck)

2. block_config_edit.py (PreToolUse)
   - リンター/フォーマッター設定ファイルの編集をブロック
   - エージェントが設定を緩和してテストをパスさせることを防止
   - 保護対象: eslint, biome, prettier, tsconfig, ruff 等

3. stop_test_verification.py (Stop)
   - エージェント完了前にテストスイートを自動実行
   - 失敗時はフィードバックを返し修正を促す
   - 無限ループ防止 (STOP_HOOK_ACTIVE), 変更なし時スキップ

settings.json と claude-settings.json の両方に登録済み。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 21, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces three new Claude Code hooks that enhance development workflows: a pre-tool-use hook preventing edits to linter/formatter config files, a post-tool-use hook that auto-formats and lints code, and a stop hook that runs tests before agent completion. Configuration and documentation files are updated to register and document these hooks.

Changes

Cohort / File(s) Summary
New Hook Scripts
.claude/hooks/block_config_edit.py, .claude/hooks/post_edit_auto_lint.py, .claude/hooks/stop_test_verification.py
Three new executable Python hooks: (1) blocks edits to protected linter/formatter configs, (2) auto-formats/lints code in TypeScript, Python, and Shell with a two-phase flow and output truncation, and (3) runs package tests on session stop with timeout and failure capture.
Hook Configuration
.claude/settings.json, .devcontainer/claude-settings.json
Updated hook registration to trigger new scripts on PreToolUse (config protection), PostToolUse (auto-linting), and Stop (test verification) events for Write|Edit|MultiEdit operations.
Documentation
README.md
Updated hooks table to document the three new hooks, their triggers, and purposes within the development workflow.

Sequence Diagram

sequenceDiagram
    participant User/Claude
    participant PreToolUse as PreToolUse<br/>block_config_edit
    participant Tool as Tool Execution<br/>(Write/Edit/MultiEdit)
    participant PostToolUse as PostToolUse<br/>post_edit_auto_lint
    participant Stop as Stop Hook<br/>stop_test_verification

    User/Claude->>PreToolUse: Initiates tool use
    PreToolUse->>PreToolUse: Read file_path from stdin
    alt Protected config file?
        PreToolUse->>User/Claude: Block edit (exit 2)
    else Safe file
        PreToolUse->>Tool: Allow tool execution (exit 0)
        Tool->>Tool: Apply edits to file
        Tool->>PostToolUse: Edits complete
        PostToolUse->>PostToolUse: Detect language<br/>(TS/JS, Python, Shell)
        PostToolUse->>PostToolUse: Phase 1: Run auto-fix tools<br/>(Biome, ruff, shellcheck)
        PostToolUse->>PostToolUse: Phase 2: Run linters<br/>Capture diagnostics
        PostToolUse->>PostToolUse: Post-process output<br/>Suppress "no issues" messages
        PostToolUse->>User/Claude: Emit diagnostics if any<br/>(exit 0)
    end
    
    User/Claude->>Stop: Session stops
    Stop->>Stop: Check for git changes
    alt Git changes exist?
        Stop->>Stop: Locate package.json<br/>Detect test script & package manager
        alt Test script found?
            Stop->>Stop: Run tests (5 min timeout)<br/>with CI=true
            alt Tests pass?
                Stop->>User/Claude: Exit silently (exit 0)
            else Tests fail
                Stop->>User/Claude: Capture last 30 lines<br/>Output failure context (exit 0)
            end
        else No test script
            Stop->>User/Claude: Exit silently (exit 0)
        end
    else No changes
        Stop->>User/Claude: Exit silently (exit 0)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • keito4/config#451: Enables PreToolUse/PostToolUse hook configuration in shared .claude/settings.json
  • keito4/config#584: Modifies .devcontainer/claude-settings.json and adds new hook scripts under .claude/hooks/
  • keito4/config#86: Updates README to document .claude/ directory and hook scripts

Suggested labels

size/M

Poem

🐰 Hop-hop, the hooks are aligned,
Config files blocked, no edits maligned,
Auto-lint dancing post-edit with grace,
Tests verify code's rightful place!
Quality gates guard the warren true. 🛡️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references three new hooks (auto-linting, config protection, pre-completion testing) which align with the main changes, but uses Japanese text that may reduce clarity for non-Japanese speakers; however, it accurately summarizes the primary additions.
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
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/harness-engineering-hooks

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 21, 2026

Copy link
Copy Markdown
Owner Author

🔍 AI Code Review (Local Hook)

Models: Codex (default) / Gemini (default)

🤖 Codex Review

以下、差分(merge-base..HEAD)のレビュー結果です。

  1. MultiEdit の入力形式に未対応でフックが実質無効になる可能性
    Write|Edit|MultiEdit にフックを付けていますが、tool_input から単一の file_path/path しか見ていません。MultiEdit では複数ファイルが配列で渡るケースがあり、その場合このフックは何も検出できず、保護対象ファイルの編集や自動リントが走らない可能性があります。
    影響: 期待した保護・自動リントが効かず、レビュー/品質ゲートが抜ける。
    該当: .claude/hooks/block_config_edit.py 行13-20、行74-86
    該当: .claude/hooks/post_edit_auto_lint.py 行16-24、行45-99

  2. npx --yes oxlint の自動実行はセキュリティ/運用上のリスク
    oxlint が未インストールの場合に npx --yes を自動実行します。編集のたびに外部パッケージ取得とコード実行が発生しうるため、CI/企業環境/オフライン環境では重大な運用・セキュリティリスクになります。明示的な許可やローカル依存への限定がない点が問題です。
    影響: 意図しない外部コード実行、ネットワークアクセス、再現性低下。
    該当: .claude/hooks/post_edit_auto_lint.py 行63-74、行78-82

判定: patch is incorrect
理由: MultiEdit を含むフック設計で実際に動作しないケースがあるため、意図した保護/自動リントが成立しない。
信頼度: 0.53


⚠️ 修正が必要です

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


🤖 Generated by post_pr_ai_review.py hook

@keito4

keito4 commented Mar 21, 2026

Copy link
Copy Markdown
Owner Author

🔍 AI Code Review (Local Hook)

Models: Codex (default) / Gemini (default)

🤖 Codex Review

以下は、マージベース 8ba9ea1c043ccf525d8ecd96b62d5a26298997cb から HEAD までの差分レビューです。

指摘事項:

  1. セキュリティ/パフォーマンス: 編集のたびに npx --yes oxlint を実行する挙動
    oxlint がローカルに無い場合、npx --yes oxlint が毎回走り得ます。これは供給網リスク(外部パッケージの自動取得・実行)と性能劣化(ネットワーク待ち・30秒タイムアウト)を編集ごとに引き起こします。
    影響範囲: .claude/hooks/post_edit_auto_lint.py:73-82
    対応案: package.jsondevDependenciesoxlint がある場合のみ実行、もしくは明示的な opt-in フラグで npx 実行を制御。

  2. 正確性: 初期コミットなしリポジトリでテストが実行されない
    git diff --name-only HEAD は初期コミットが無いリポジトリで失敗し得ますが、戻り値を確認していないため「変更なし」と誤判定してテストをスキップします。
    影響範囲: .claude/hooks/stop_test_verification.py:37-57
    対応案: git status --porcelain を使うか、git rev-parse --verify HEAD で初期コミット有無を判定して分岐。


patch is incorrect
理由: 上記の通り、供給網リスクと初期コミット時のテスト非実行という実用上の問題が導入されています。
信頼度: 0.58


⚠️ 修正が必要です

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


🤖 Generated by post_pr_ai_review.py hook

@claude

claude Bot commented Mar 21, 2026

Copy link
Copy Markdown
Contributor

Claude Code レビュー

PR の目的(エージェントが設定を緩和したりテスト未検証で完了したりするのを防ぐ)は明確で価値があります。全体的な設計は良好ですが、いくつか指摘事項があります。


🔴 要対応

1. block_config_edit.py — import の位置が PEP 8 違反

# 現状: PROTECTED_BASENAMES の定義後に import
from pathlib import PurePosixPath

from pathlib import PurePosixPath が PROTECTED_BASENAMES セット定義のに置かれています。Python は実行時に問題なく動きますが、PEP 8 では全 import をファイル先頭に置くよう定めており、ruffpyflakes の CI チェックで指摘される可能性があります。

修正案:

import sys
import json
from pathlib import PurePosixPath  # ← ここに移動

data = json.load(sys.stdin)
...

2. post_edit_auto_lint.pynpx --yes による暗黙のパッケージ自動インストール

run_silent(["npx", "--yes", "oxlint", "--fix", file_str])
diagnostics = run_capture(["npx", "--yes", "oxlint", file_str])

--yes フラグはユーザー確認なしに oxlint をダウンロード・インストールします。フック実行の度に外部パッケージを自動取得するのはセキュリティポリシー上問題になる場合があります。

修正案: oxlint が存在しない場合はスキップするか、フォールバックを eslint にする。

# npx フォールバックは削除し、ツールが存在する場合のみ実行
if shutil.which("oxlint"):
    diagnostics = run_capture(["oxlint", file_str])
# npx fallback は削除

🟡 軽微な問題

3. post_edit_auto_lint.pybiome format + biome check の二重実行

run_silent(["biome", "format", "--write", file_str])
run_silent(["biome", "check", "--fix", file_str])

biome check --fix にはフォーマットも含まれているため、biome format --write は冗長です。どちらか一方で十分です。

修正案:

if shutil.which("biome"):
    run_silent(["biome", "check", "--fix", file_str])  # format も内包

4. post_edit_auto_lint.py — ゼロ件チェックのパターンが脆弱

if "0 warnings and 0 errors" in lower or "found 0 " in lower:

"found 0 " の末尾スペースは "found 0utput" 等を防ぐ工夫ですが、ツールのメッセージフォーマットが変わると機能しなくなります。終了コードで判断する方がより堅牢です。

修正案: run_capture を exit code も返すよう拡張し、returncode == 0 の場合は diagnostics を空にする。


5. stop_test_verification.py — 未追跡ファイルによる誤トリガー

untracked_result = subprocess.run(
    ["git", "ls-files", "--others", "--exclude-standard"],
    ...
)
has_changes = bool(
    ...
    or (untracked_result.stdout or "").strip()
)

.gitignore 対象外の未追跡ファイル(例: .env.local、ビルド成果物等)が存在するだけでテストが毎回実行されます。セッション固有の作業変更のみを検出したい場合、git status --porcelain でステージング済み+変更済みのみに絞るか、未追跡ファイルのチェックを除外するほうがシンプルです。


6. block_config_edit.pytsconfig.*.json パターンが未カバー

tsconfig.json のみが保護対象ですが、tsconfig.base.jsontsconfig.app.jsontsconfig.build.json 等のバリアントが対象外です。basename.startswith("tsconfig") and basename.endswith(".json") のような判定も検討できます。


✅ 良い点

  • 無限ループ防止 (STOP_HOOK_ACTIVE) の実装が適切
  • タイムアウト設定 が全 subprocess に付いている
  • パッケージマネージャー自動判定 のロジックが明確
  • git diff HEADgit diff --cached の両方を見てステージング済み変更を漏れなく検出している
  • Hook の登録が settings.jsonclaude-settings.json の両方に反映されている

まとめ

優先度 件数
🔴 要対応 2件
🟡 軽微 4件
✅ 良好 多数

Import 位置の修正(#1)と npx --yes の削除(#2)は最低限対応を推奨します。他はオプションですが、堅牢性が上がります。

🤖 Generated with Claude Code

@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: 44bbbc1f85

ℹ️ 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".

# 問題がない場合はスキップ(oxlint の "Found 0 warnings and 0 errors" 等)
if diagnostics:
lower = diagnostics.lower()
if "0 warnings and 0 errors" in lower or "found 0 " in lower:

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 Do not drop lint errors when warning count is zero

The success filter "found 0 " is too broad and clears diagnostics even when errors remain (for example, summaries like Found 0 warnings and N errors). In that case additionalContext is never emitted, so the auto-fix loop silently misses real lint failures and can allow completion with unresolved issues.

Useful? React with 👍 / 👎.

Comment on lines +94 to +98
[PM, "run", test_script],
capture_output=True, text=True, timeout=300, cwd=repo_root,
env={**os.environ, "CI": "true", "STOP_HOOK_ACTIVE": "1"},
)
except subprocess.TimeoutExpired:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Catch missing package manager executable in Stop hook

This block only handles TimeoutExpired, but subprocess.run([PM, "run", ...]) can also raise FileNotFoundError when the lockfile-selected package manager (pnpm/yarn/bun) is not installed in the current environment. That causes the hook to crash instead of gracefully skipping or reporting, which can interrupt the completion flow.

Useful? React with 👍 / 👎.

@keito4 keito4 self-assigned this Mar 21, 2026

@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.

🧹 Nitpick comments (4)
.claude/hooks/block_config_edit.py (1)

73-76: Consider moving import to the top of the file.

The from pathlib import PurePosixPath import on line 74 is placed after the early-exit logic, which is unconventional. While this works and may be intentional for micro-optimization (avoiding import if path is empty), it violates PEP 8 style conventions.

♻️ Move import to top
 import sys
 import json
+from pathlib import PurePosixPath
 
 data = json.load(sys.stdin)

Then remove line 74:

 # ── パス判定 ───────────────────────────────────────────────
-from pathlib import PurePosixPath
-
 basename = PurePosixPath(file_path).name
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/block_config_edit.py around lines 73 - 76, Move the inline
import into the module top-level: remove the in-function/in-block "from pathlib
import PurePosixPath" and add that import alongside other imports at the top of
the file, then keep the existing usage of PurePosixPath(file_path).name (the
basename variable) unchanged; this restores PEP8 style and avoids an inline
import while preserving the logic in the basename computation that uses
PurePosixPath and file_path.
.claude/hooks/post_edit_auto_lint.py (1)

96-102: Simplify the "no issues" detection logic.

The conditions for clearing diagnostics can be combined. Also, the comment on line 100 starts with # ruff: which may confuse static analysis tools expecting a directive format.

♻️ Consolidated condition
 # 問題がない場合はスキップ(oxlint の "Found 0 warnings and 0 errors" 等)
 if diagnostics:
     lower = diagnostics.lower()
-    if "0 warnings and 0 errors" in lower or "found 0 " in lower:
-        diagnostics = ""
-    # ruff: "All checks passed!" をスキップ
-    if "all checks passed" in lower:
+    # oxlint: "0 warnings and 0 errors", ruff: "All checks passed!" をスキップ
+    if any(phrase in lower for phrase in [
+        "0 warnings and 0 errors",
+        "found 0 ",
+        "all checks passed",
+    ]):
         diagnostics = ""
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/post_edit_auto_lint.py around lines 96 - 102, The diagnostics
cleanup logic should combine the multiple substring checks into a single
conditional: compute lower = diagnostics.lower() and if any of the "no issues"
phrases (e.g., "0 warnings and 0 errors", "found 0 ", or "all checks passed")
are present then set diagnostics = "". Update the comment above this block to
remove the `# ruff:` prefix (or rewrite it as a plain explanatory comment) so
linters won't treat it as a directive; keep references to the diagnostics
variable and the lower local to help locate the change.
.claude/hooks/stop_test_verification.py (2)

82-90: Consider adding test:ci to test script candidates.

Many projects define test:ci for CI environments. Since this hook sets CI=true, running test:ci when available might be more appropriate.

♻️ Add test:ci to the list
 # ── テスト実行 ────────────────────────────────────────────
-TEST_SCRIPTS = ["test", "test:unit"]
+TEST_SCRIPTS = ["test:ci", "test", "test:unit"]
 test_script = None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/stop_test_verification.py around lines 82 - 90, Update the
TEST_SCRIPTS candidate list to include "test:ci" (preferably before "test") so
the hook will pick and run a CI-specific test script when present; modify the
TEST_SCRIPTS constant referenced by the loop that sets test_script (and keeps
the existing fallback to "test" and "test:unit") so the detection logic in the
for s in TEST_SCRIPTS: / if s in scripts: block will choose "test:ci" when
available.

36-43: Potential edge case: initial commit with no HEAD.

git diff --name-only HEAD will fail on a repository with no commits yet. While rare, this could cause the hook to silently skip (due to exception handling), which is acceptable behavior, but worth noting.

📝 Alternative using --cached for initial commit safety
 try:
     diff_result = subprocess.run(
-        ["git", "diff", "--name-only", "HEAD"],
+        ["git", "diff", "--name-only"],
         capture_output=True, text=True, timeout=10, cwd=repo_root
     )

Note: Using git diff --name-only (without HEAD) shows unstaged changes, while git diff --cached --name-only shows staged changes. Your current approach combining both is correct, but the HEAD reference could fail on initial commits.

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

In @.claude/hooks/stop_test_verification.py around lines 36 - 43, The code calls
subprocess.run(["git","diff","--name-only","HEAD"], ...) which will fail on a
repository with no commits; before running that diff use
subprocess.run(["git","rev-parse","--verify","HEAD"], capture_output=True,
text=True, timeout=5, cwd=repo_root) to detect an initial commit and, if it
returns non-zero, treat diff_result as empty (skip running git diff HEAD or set
diff_names = ""), otherwise run the existing diff command; update the logic
around diff_result and the existing staged_result handling to account for this
fallback so functions using diff_result (e.g., diff_result.stdout parsing) won’t
break on initial commits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.claude/hooks/block_config_edit.py:
- Around line 73-76: Move the inline import into the module top-level: remove
the in-function/in-block "from pathlib import PurePosixPath" and add that import
alongside other imports at the top of the file, then keep the existing usage of
PurePosixPath(file_path).name (the basename variable) unchanged; this restores
PEP8 style and avoids an inline import while preserving the logic in the
basename computation that uses PurePosixPath and file_path.

In @.claude/hooks/post_edit_auto_lint.py:
- Around line 96-102: The diagnostics cleanup logic should combine the multiple
substring checks into a single conditional: compute lower = diagnostics.lower()
and if any of the "no issues" phrases (e.g., "0 warnings and 0 errors", "found 0
", or "all checks passed") are present then set diagnostics = "". Update the
comment above this block to remove the `# ruff:` prefix (or rewrite it as a
plain explanatory comment) so linters won't treat it as a directive; keep
references to the diagnostics variable and the lower local to help locate the
change.

In @.claude/hooks/stop_test_verification.py:
- Around line 82-90: Update the TEST_SCRIPTS candidate list to include "test:ci"
(preferably before "test") so the hook will pick and run a CI-specific test
script when present; modify the TEST_SCRIPTS constant referenced by the loop
that sets test_script (and keeps the existing fallback to "test" and
"test:unit") so the detection logic in the for s in TEST_SCRIPTS: / if s in
scripts: block will choose "test:ci" when available.
- Around line 36-43: The code calls
subprocess.run(["git","diff","--name-only","HEAD"], ...) which will fail on a
repository with no commits; before running that diff use
subprocess.run(["git","rev-parse","--verify","HEAD"], capture_output=True,
text=True, timeout=5, cwd=repo_root) to detect an initial commit and, if it
returns non-zero, treat diff_result as empty (skip running git diff HEAD or set
diff_names = ""), otherwise run the existing diff command; update the logic
around diff_result and the existing staged_result handling to account for this
fallback so functions using diff_result (e.g., diff_result.stdout parsing) won’t
break on initial commits.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bd559b2a-5559-4526-b2cc-d87f6f04c412

📥 Commits

Reviewing files that changed from the base of the PR and between 8ba9ea1 and 44bbbc1.

📒 Files selected for processing (6)
  • .claude/hooks/block_config_edit.py
  • .claude/hooks/post_edit_auto_lint.py
  • .claude/hooks/stop_test_verification.py
  • .claude/settings.json
  • .devcontainer/claude-settings.json
  • README.md

@keito4
keito4 merged commit 552d4a8 into main Mar 21, 2026
19 checks passed
@keito4
keito4 deleted the feat/harness-engineering-hooks branch March 21, 2026 02:25
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.99.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