diff --git a/.claude/settings.json b/.claude/settings.json index 0d6060e..0aa939b 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -108,6 +108,10 @@ { "matcher": "", "hooks": [ + { + "type": "command", + "command": "bash scripts/sync_signal.sh check 2>/dev/null || true" + }, { "type": "command", "command": "bash scripts/git_fetch_throttle.sh 2>/dev/null || true" diff --git a/scripts/git_fetch_throttle.sh b/scripts/git_fetch_throttle.sh index 89d083b..b363021 100644 --- a/scripts/git_fetch_throttle.sh +++ b/scripts/git_fetch_throttle.sh @@ -1,9 +1,11 @@ #!/bin/bash -# UserPromptSubmit hook — 실시간 원격 동기화 (2026-04-17 강화) +# UserPromptSubmit hook — 보조(fallback) 원격 동기화 # 변경 이력: # - 2026-04-15: 5분 throttle fetch + ff-only merge (초기) -# - 2026-04-17: throttle 30초로 단축 + 자동 stash/pop + merge 강화 -# (PD님 지시: "항상 실시간으로 공유되어서 다른 세션에서도 확인") +# - 2026-04-17 AM: throttle 30초 단축 (polling 시도) +# - 2026-04-17 PM: 300초 복원. PD님 지적 "30초 polling은 네트워크 부하 + 근본 해결 아님". +# 주 동기화는 scripts/sync_signal.sh (로컬 IPC 시그널) 담당. 본 스크립트는 +# 시그널이 없거나 다른 PC에서 push된 경우를 위한 fallback. THROTTLE_DIR="$HOME/.claude/.nerdnavis_throttle" mkdir -p "$THROTTLE_DIR" 2>/dev/null @@ -13,7 +15,7 @@ GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) REPO_HASH=$(echo "$GIT_DIR" | sha1sum 2>/dev/null | cut -d' ' -f1) THROTTLE_FILE="$THROTTLE_DIR/last_fetch_$REPO_HASH" -THROTTLE_SECONDS=30 # 2026-04-17: 300 → 30초 (실시간 동기화 보장) +THROTTLE_SECONDS=300 # fallback 역할 — 주 동기화는 sync_signal.sh if [ -f "$THROTTLE_FILE" ]; then LAST=$(cat "$THROTTLE_FILE" 2>/dev/null || echo 0) diff --git a/scripts/sync_push.sh b/scripts/sync_push.sh new file mode 100644 index 0000000..5023c52 --- /dev/null +++ b/scripts/sync_push.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# sync_push.sh — 자동 push + 시그널 갱신 일괄 실행 +# +# C20-1-A 자동 push 정책 이행 표준 절차: +# git push origin main → sync_signal.sh update (로컬 IPC 시그널 갱신) +# +# PM은 업무 완료 시 본 스크립트 1회 실행으로 push·시그널 갱신 동시 수행. + +cd "$(dirname "$0")/.." 2>/dev/null + +BRANCH="${1:-main}" + +echo "▶️ git push origin $BRANCH" +if git push origin "$BRANCH" 2>&1 | tail -3; then + echo "✅ push 완료" +else + echo "❌ push 실패 — 시그널 갱신 건너뜀" + exit 1 +fi + +bash scripts/sync_signal.sh update +echo "📡 시그널 갱신 완료 — 다른 세션이 다음 프롬프트에서 즉시 감지" diff --git a/scripts/sync_signal.sh b/scripts/sync_signal.sh new file mode 100644 index 0000000..afc9d8b --- /dev/null +++ b/scripts/sync_signal.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# sync_signal.sh — 로컬 IPC 시그널 기반 실시간 동기화 +# +# 설계 (2026-04-17 PD님 직접 제안): +# polling 방식(throttle fetch)은 네트워크 부하 유발 + 근본 해결 아님. +# 대신 "공유할 사항 발생 시 플래그 데이터 갱신 → 수신 측이 플래그만 체크" +# 구조로 전환. 플래그 변경 감지 시에만 pull 수행하므로 네트워크 비용 최소화. +# +# 사용: +# bash sync_signal.sh update # push 성공 시 호출: 플래그 파일 갱신 +# bash sync_signal.sh check # UserPromptSubmit hook: 플래그 변경 시 pull + +BUS_DIR="$HOME/.claude/.nerdnavis_bus" +mkdir -p "$BUS_DIR" 2>/dev/null + +GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) +[ -z "$GIT_DIR" ] && exit 0 + +REPO_HASH=$(echo "$GIT_DIR" | sha1sum 2>/dev/null | cut -d' ' -f1) +SIGNAL_FILE="$BUS_DIR/signal_$REPO_HASH" +SESSION_LAST_FILE="$BUS_DIR/last_seen_$REPO_HASH.$$" + +MODE="${1:-check}" + +# ============================================================ +# update 모드: push 성공 후 호출. 로컬 HEAD + timestamp를 시그널에 기록 +# ============================================================ +if [ "$MODE" = "update" ]; then + HEAD=$(git rev-parse HEAD 2>/dev/null) + if [ -n "$HEAD" ]; then + echo "$HEAD $(date +%s)" > "$SIGNAL_FILE" + fi + exit 0 +fi + +# ============================================================ +# check 모드: 플래그 파일 변경 감지 시에만 pull (네트워크 비용 최소화) +# ============================================================ + +[ -f "$SIGNAL_FILE" ] || exit 0 + +CURRENT=$(cat "$SIGNAL_FILE" 2>/dev/null) +LAST=$(cat "$SESSION_LAST_FILE" 2>/dev/null) + +# 플래그가 자기 세션이 마지막 본 것과 같으면 — 네트워크 호출 없이 종료 +if [ "$CURRENT" = "$LAST" ]; then + exit 0 +fi + +# 플래그 변경 감지 → fetch + merge 수행 +CURRENT_HEAD=$(echo "$CURRENT" | awk '{print $1}') +LOCAL_HEAD=$(git rev-parse HEAD 2>/dev/null) + +# 이미 로컬이 최신이면 (스스로 push한 세션) — 플래그만 동기화 +if [ "$CURRENT_HEAD" = "$LOCAL_HEAD" ]; then + echo "$CURRENT" > "$SESSION_LAST_FILE" + exit 0 +fi + +git fetch origin 2>/dev/null + +CHANGES=$(git log --oneline HEAD..origin/main 2>/dev/null | head -5) +if [ -n "$CHANGES" ]; then + echo "📡 [signal-sync] 플래그 변경 감지 — 원격 변경 자동 반영:" + echo "$CHANGES" + + # 로컬 미커밋 안전 stash + STASHED=0 + if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then + if git stash push -u -m "signal-sync-$(date +%s)" > /dev/null 2>&1; then + STASHED=1 + fi + fi + + if git merge origin/main --no-edit --ff-only 2>/dev/null; then + echo "✅ 실시간 동기화 완료 (fast-forward)" + elif git merge origin/main --no-edit 2>/dev/null; then + echo "✅ 실시간 동기화 완료 (merge commit)" + else + echo "⚠️ 자동 merge 실패 — 수동 해결 필요 (git merge origin/main)" + git merge --abort 2>/dev/null + fi + + if [ "$STASHED" -eq 1 ]; then + git stash pop > /dev/null 2>&1 || echo "⚠️ stash pop 실패 — git stash list 확인 필요" + fi +fi + +echo "$CURRENT" > "$SESSION_LAST_FILE" +exit 0