.claude/hooks/ 配下(フック本体・フックから呼ばれるスクリプト・tests/ のテスト)を作成・修正するときは本ルールに従うこと.フックはテンプレートから派生した全プロジェクトで,開発者ごとに異なる OS 上で動く.1 つの OS でしか確かめていない修正は,他の OS で検出漏れ(安全装置の素通り)や誤ブロックを起こしうる.
.claude/hooks/tests が全件通ることを完成条件とする.手元の OS だけで通った状態は未完成として扱う.github/workflows/hooks-ci.yml(windows-latest / macos-latest / ubuntu-latest のマトリクス)が行う.PR の CI が 3 OS とも緑であることを確認してからマージする/sync-template で派生プロジェクトには配布しない.派生プロジェクトでフックの不具合を見つけた場合は,テンプレートリポジトリ側で修正して CI で 3 OS を確認し,/sync-template で取り込むpython -B -m unittest discover -s .claude/hooks/tests(python が無い環境では python3)を実行する.Windows ホストで WSL が使える場合は,リポジトリを WSL 側の一時ディレクトリ以外の場所に複製して python3 -B -m unittest discover -s .claude/hooks/tests を実行すると Linux の挙動も事前に確認できるrun_python.sh が拾う Python は環境により古い場合がある.TestPython37Compat が検査する)os.path はホスト OS によって ntpath(Windows)と posixpath(macOS / Linux)に切り替わる.区切り文字(\ を区切りと見なすか),絶対パスの判定(isabs),ドライブレター,大文字小文字の区別が OS ごとに異なることを前提に書くos.path と異なる場合は,判定の前に明示的に正規化する(例: Linux / macOS の pwsh は \ も区切りとして受け付けるため,POSIX ホストでは PowerShell のパスの \ を / に揃えてから isabs・join・normpath に渡す)/ で始まるか」のような,ある OS でだけ成り立つ前提で分岐しない(例: cmd.exe のスイッチ /s と POSIX の絶対パス /workspace/x を区別できる判定にする)ntpath.isabs の結果に直接依存させない.Python 3.13 で ntpath.isabs が変わり,ドライブ無しの root-relative パス(/tmp/x・\tmp\x)を False と判定するようになったため,そのまま使うと cwd と結合されて D:\tmp\x 等に化け,Python のバージョンで判定が変わる(フックでは is_absolute で Windows の /・\ 始まりを常に絶対パスとして扱う)/c/Users/...)・ドライブレター・UNC パス等の Windows 固有の変換は os.name == "nt" のときだけ行い,他 OS の挙動を変えない*.sh)は macOS 標準の bash 3.2 と BSD 版コマンドでも動く書き方にする(GNU 拡張のオプションや bash 4 以降の構文に頼らない)cmd /c・ドライブレター・Git Bash 形式 /c/... 等,特定 OS にしか存在しない入力)は @unittest.skipUnless(os.name == "nt", "理由") 等で実行する OS を明示的に限定する.skip の理由には「なぜその OS 限定か」を書く.. による脱出の検出・削除/上書きの判定等)は skip せず全 OS で実行する.OS 依存の書き方で失敗したテストを skip で黙らせてはならない(本物の検出漏れを隠す)os.path.join や tempfile で組み立て,\ や C: をハードコードしない(OS 固有ケースとして限定したテストを除く)