diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..8d458aa --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,16 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Edit|Write|NotebookEdit", + "hook": "bash /Users/shunsukehayashi/dev/platform/miyabi-cli-standalone/scripts/hook-check-lock.sh \"$TOOL_INPUT\"" + } + ], + "PostToolUse": [ + { + "matcher": "Bash", + "hook": "bash /Users/shunsukehayashi/dev/platform/miyabi-cli-standalone/scripts/hook-post-bash.sh \"$TOOL_INPUT\"" + } + ] + } +} diff --git a/scripts/hook-check-lock.sh b/scripts/hook-check-lock.sh new file mode 100755 index 0000000..856d160 --- /dev/null +++ b/scripts/hook-check-lock.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# Claude Code PreToolUse Hook: ファイル編集前にロック確認 +# +# Edit/Write ツールが呼ばれる前に実行される。 +# ロックされていないファイルへの書き込みをブロックする。 + +TOOL_INPUT="$1" +MIYABI_BIN="/Users/shunsukehayashi/dev/platform/miyabi-cli-standalone/target/release/miyabi" +STORE="/Users/shunsukehayashi/dev/platform/miyabi-cli-standalone/project_memory/tasks.json" + +# miyabi バイナリがなければスキップ +if [ ! -x "$MIYABI_BIN" ]; then + exit 0 +fi + +# tasks.json がなければスキップ(初回) +if [ ! -f "$STORE" ]; then + exit 0 +fi + +# 編集対象ファイルを抽出(file_path パラメータ) +TARGET_FILE=$(echo "$TOOL_INPUT" | python3 -c " +import sys, json +try: + data = json.loads(sys.stdin.read()) + print(data.get('file_path', '')) +except: + pass +" 2>/dev/null) + +if [ -z "$TARGET_FILE" ]; then + exit 0 +fi + +# リポルートからの相対パスに変換 +REPO_ROOT="/Users/shunsukehayashi/dev/platform/miyabi-cli-standalone" +REL_PATH="${TARGET_FILE#$REPO_ROOT/}" + +# ロック一覧を取得 +LOCKS=$("$MIYABI_BIN" gate --store-path "$STORE" --format json locks 2>/dev/null) + +# このファイルがロックされているか確認 +LOCK_INFO=$(echo "$LOCKS" | python3 -c " +import sys, json +try: + data = json.loads(sys.stdin.read()) + if isinstance(data, dict): + for file, info in data.items(): + if file == '$REL_PATH' or '$REL_PATH'.endswith(file): + print(f'{info.get(\"agent\",\"?\")}@{info.get(\"node\",\"?\")}') + break +except: + pass +" 2>/dev/null) + +# ロックが存在し、かつ自分のロックでない場合はブロック +if [ -n "$LOCK_INFO" ]; then + POLARIS_AGENT="${POLARIS_AGENT_ID:-claude}" + if echo "$LOCK_INFO" | grep -qv "$POLARIS_AGENT"; then + echo "⚠️ POLARIS: $REL_PATH は $LOCK_INFO がロック中です。" + echo "miyabi gate assign でロックを取得してください。" + # exit 2 でブロック(Claude Code はこれでツール実行を中止する) + exit 2 + fi +fi + +# ロックがない場合も警告(ただしブロックはしない) +ACTIVE_LOCKS=$("$MIYABI_BIN" gate --store-path "$STORE" locks 2>/dev/null | grep -c "->") +if [ "$ACTIVE_LOCKS" -gt 0 ]; then + # 他のファイルにロックがある場合、このファイルにロックがないことを警告 + HAS_LOCK=$(echo "$LOCKS" | python3 -c " +import sys, json +try: + data = json.loads(sys.stdin.read()) + if isinstance(data, dict) and '$REL_PATH' in data: + print('yes') +except: + pass +" 2>/dev/null) + + if [ -z "$HAS_LOCK" ]; then + echo "ℹ️ POLARIS: $REL_PATH はロックされていません。miyabi gate assign で登録を推奨します。" + fi +fi + +exit 0 diff --git a/scripts/hook-post-bash.sh b/scripts/hook-post-bash.sh new file mode 100755 index 0000000..141c654 --- /dev/null +++ b/scripts/hook-post-bash.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Claude Code PostToolUse Hook: Bash 実行後にロック状態をリマインド +# +# git commit が実行された場合、post-commit hook が発火するので +# ここでは軽い状態表示のみ。 + +TOOL_INPUT="$1" +MIYABI_BIN="/Users/shunsukehayashi/dev/platform/miyabi-cli-standalone/target/release/miyabi" +STORE="/Users/shunsukehayashi/dev/platform/miyabi-cli-standalone/project_memory/tasks.json" + +# miyabi バイナリがなければスキップ +if [ ! -x "$MIYABI_BIN" ]; then + exit 0 +fi + +# git commit を検出した場合にステータス表示 +if echo "$TOOL_INPUT" | grep -q "git commit"; then + ACTIVE=$("$MIYABI_BIN" gate --store-path "$STORE" locks 2>/dev/null | grep -c "->") + if [ "$ACTIVE" -gt 0 ]; then + echo "ℹ️ POLARIS: $ACTIVE 件のファイルがまだロック中です。作業完了したら miyabi gate merge または miyabi gate manual-complete を実行してください。" + fi +fi + +exit 0