diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index b669167..3a214e3 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -61,6 +61,12 @@ Auto-detect on every user message (first match wins): On mode change: announce `[MODE -> infra]`, tell user to run `/color `. Full details: `.claude/commands/mode.md` +**MANDATORY on every mode change:** write the new mode to `.claude/current-mode` so hooks can read it: +```bash +echo dev > .claude/current-mode # substitute the actual mode name +``` +This file is gitignored (machine-local). The `UserPromptSubmit` hook reads it to gate the lock check on dev mode. + --- ## Identity: You Are a Coordinator diff --git a/.claude/scripts/check-messages.sh b/.claude/scripts/check-messages.sh index 79c1be3..fce015b 100644 --- a/.claude/scripts/check-messages.sh +++ b/.claude/scripts/check-messages.sh @@ -1,26 +1,51 @@ #!/usr/bin/env bash -# Checks for unread coord messages and injects them into Claude's context. -# Runs as a UserPromptSubmit hook — exits silently if no messages or API is down. +# UserPromptSubmit hook — injects unread coord messages and (in dev mode) active locks. SESSION="$(hostname)/claude-main" API="http://172.16.3.30:8001" +SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +MODE_FILE="${SCRIPT_DIR}/current-mode" + +# --- Unread messages --------------------------------------------------------- result=$(curl -s --connect-timeout 3 "${API}/api/coord/messages?to_session=${SESSION}&unread_only=true" 2>/dev/null) -[ -z "$result" ] && exit 0 -count=$(echo "$result" | jq '.total' 2>/dev/null) -[ -z "$count" ] || [ "$count" -eq 0 ] && exit 0 +if [ -n "$result" ]; then + count=$(echo "$result" | jq '.total' 2>/dev/null) + if [ -n "$count" ] && [ "$count" -gt 0 ]; then + echo "" + echo "============================================================" + echo "UNREAD COORD MESSAGES ($count)" + echo "============================================================" + echo "$result" | jq -r '.messages[] | "FROM: \(.from_session)\nDATE: \(.created_at)\nSUBJECT: \(.subject)\n\nMESSAGE:\n\(.body)\n---"' + echo "============================================================" + echo "" -echo "" -echo "============================================================" -echo "UNREAD COORD MESSAGES ($count)" -echo "============================================================" -echo "$result" | jq -r '.messages[] | "FROM: \(.from_session)\nDATE: \(.created_at)\nSUBJECT: \(.subject)\n\nMESSAGE:\n\(.body)\n---"' -echo "============================================================" -echo "" + # Mark all fetched messages as read immediately + echo "$result" | jq -r '.messages[].id' | tr -d '\r' | while read -r id; do + curl -s -X PUT "${API}/api/coord/messages/${id}/read" >/dev/null 2>&1 + done + fi +fi -# Mark all fetched messages as read immediately -echo "$result" | jq -r '.messages[].id' | tr -d '\r' | while read -r id; do - curl -s -X PUT "${API}/api/coord/messages/${id}/read" >/dev/null 2>&1 -done +# --- Active locks (dev mode only) ------------------------------------------- + +current_mode="" +[ -f "$MODE_FILE" ] && current_mode=$(cat "$MODE_FILE" | tr -d '[:space:]') + +if [ "$current_mode" = "dev" ]; then + locks=$(curl -s --connect-timeout 3 "${API}/api/coord/locks" 2>/dev/null) + if [ -n "$locks" ]; then + lock_count=$(echo "$locks" | jq '.total' 2>/dev/null) + if [ -n "$lock_count" ] && [ "$lock_count" -gt 0 ]; then + echo "" + echo "============================================================" + echo "[WARNING] ACTIVE LOCKS ($lock_count) — check before editing" + echo "============================================================" + echo "$locks" | jq -r '.locks[] | "[DEV MODE] LOCK: \(.project_key) / \(.resource)\n Held by: \(.session_id)\n Reason: \(.description // "none")\n Expires: \(.expires_at // "unknown")\n---"' + echo "============================================================" + echo "" + fi + fi +fi exit 0 diff --git a/.gitignore b/.gitignore index f6f475a..7a6d987 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ tmp-remediation/ # Local settings (machine-specific) .claude/settings.local.json .claude/identity.json +.claude/current-mode # Temporary files *.tmp