103 lines
4.2 KiB
Bash
103 lines
4.2 KiB
Bash
#!/bin/bash
|
|
# SessionStart hook — memory/org junction을 $HOME/.claude/nerdnavis-memory/로 보장
|
|
# Claude user memory 경로(`$HOME/.claude/projects/*/memory`)의 모든 worktree 해시 폴더를
|
|
# 중앙 저장소로 연결하여 worktree 경계 무관 조직 기억 실시간 공유 보장.
|
|
# 2026-04-19 신설 — C34 확장 (P25 승격 + memory/org/ 편입)
|
|
# 관련 규칙: C34 · C16-1 · C34-16 memory junction 특수 조항 · 헌법 제1원칙 ⑤
|
|
|
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
[ -z "$REPO_ROOT" ] && exit 0
|
|
|
|
CENTRAL_MEM="$HOME/.claude/nerdnavis-memory"
|
|
MARKER_NAME=".memory-junction-marker"
|
|
CLAUDE_PROJECTS="$HOME/.claude/projects"
|
|
LOCK_FILE="$HOME/.claude/.nerdnavis_memory_junction.lock"
|
|
|
|
# 0. Lock (race condition 방지, 동시 세션 시작 시 junction 중복 시도 차단)
|
|
ATTEMPT=0
|
|
while [ -f "$LOCK_FILE" ] && [ "$ATTEMPT" -lt 5 ]; do
|
|
sleep 1
|
|
ATTEMPT=$((ATTEMPT + 1))
|
|
done
|
|
echo "$$" > "$LOCK_FILE" 2>/dev/null
|
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
|
|
|
# 1. 중앙 저장소 + marker 보장
|
|
mkdir -p "$CENTRAL_MEM" 2>/dev/null
|
|
if [ ! -f "$CENTRAL_MEM/$MARKER_NAME" ]; then
|
|
echo "nerdnavis-memory central junction target (C34-16, 2026-04-19)" > "$CENTRAL_MEM/$MARKER_NAME" 2>/dev/null
|
|
fi
|
|
|
|
# 2. Claude projects base 부재 시 조기 종료 (Claude Code 첫 실행 전 PC)
|
|
[ ! -d "$CLAUDE_PROJECTS" ] && exit 0
|
|
|
|
# 3. E--NerdNavisAi* 패턴 해시 폴더 순회 (루트·worktree 모두 포괄)
|
|
RECONNECTED=0
|
|
CREATED=0
|
|
SKIPPED=0
|
|
FAILED=0
|
|
|
|
for hash_dir in "$CLAUDE_PROJECTS"/E--NerdNavisAi*; do
|
|
[ -d "$hash_dir" ] || continue
|
|
mem_link="$hash_dir/memory"
|
|
|
|
# 이미 중앙으로 연결된 경우 (sentinel 경유 판정)
|
|
if [ -f "$mem_link/$MARKER_NAME" ]; then
|
|
SKIPPED=$((SKIPPED + 1))
|
|
continue
|
|
fi
|
|
|
|
# 기존 link 제거 (junction/symlink/실체 디렉토리 모두) — Windows junction은 bash `-L`에 잡히지 않으므로 PowerShell reparse point 체크 선행
|
|
if [ -e "$mem_link" ] || [ -L "$mem_link" ]; then
|
|
IS_REPARSE="False"
|
|
if command -v powershell >/dev/null 2>&1; then
|
|
LINK_WIN=$(cygpath -w "$mem_link" 2>/dev/null || echo "$mem_link")
|
|
IS_REPARSE=$(powershell -NoProfile -ExecutionPolicy Bypass -Command "try { ((Get-Item -Force '$LINK_WIN' -ErrorAction Stop).Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 } catch { \$false }" 2>/dev/null | tr -d '\r\n ')
|
|
fi
|
|
|
|
if [ "$IS_REPARSE" = "True" ] || [ -L "$mem_link" ]; then
|
|
# junction/symlink 제거 (타깃 디렉토리 보호)
|
|
if command -v powershell >/dev/null 2>&1; then
|
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "Remove-Item '$LINK_WIN' -Force -Recurse -ErrorAction SilentlyContinue" >/dev/null 2>&1
|
|
else
|
|
rm -f "$mem_link" 2>/dev/null
|
|
fi
|
|
elif [ -d "$mem_link" ]; then
|
|
# 실체 디렉토리 — 내용 중앙 흡수 후 백업 (C6-1 원본 보호)
|
|
for f in "$mem_link"/*.md "$mem_link"/*.json; do
|
|
[ -f "$f" ] || continue
|
|
basename=$(basename "$f")
|
|
[ ! -f "$CENTRAL_MEM/$basename" ] && cp "$f" "$CENTRAL_MEM/$basename" 2>/dev/null
|
|
done
|
|
mv "$mem_link" "$mem_link.bak-$(date +%Y%m%d%H%M%S)" 2>/dev/null || continue
|
|
fi
|
|
fi
|
|
|
|
# 중앙으로 Junction 생성
|
|
if command -v powershell >/dev/null 2>&1; then
|
|
# Windows — PowerShell New-Item Junction (cmd //c mklink 대비 신뢰성 우위, 2026-04-18 실증)
|
|
CENTRAL_WIN=$(cygpath -w "$CENTRAL_MEM" 2>/dev/null || echo "$CENTRAL_MEM")
|
|
LINK_WIN=$(cygpath -w "$mem_link" 2>/dev/null || echo "$mem_link")
|
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "New-Item -ItemType Junction -Path '$LINK_WIN' -Target '$CENTRAL_WIN' -Force | Out-Null" >/dev/null 2>&1
|
|
else
|
|
ln -s "$CENTRAL_MEM" "$mem_link" 2>/dev/null
|
|
fi
|
|
|
|
if [ -f "$mem_link/$MARKER_NAME" ]; then
|
|
CREATED=$((CREATED + 1))
|
|
else
|
|
FAILED=$((FAILED + 1))
|
|
fi
|
|
done
|
|
|
|
# 4. 결과 보고 (변경 있을 때만)
|
|
if [ "$CREATED" -gt 0 ] || [ "$FAILED" -gt 0 ]; then
|
|
echo "🧠 [Memory Junction] 신규 연결 $CREATED · 기존 유지 $SKIPPED · 실패 $FAILED (중앙: $CENTRAL_MEM)"
|
|
fi
|
|
|
|
if [ "$FAILED" -gt 0 ]; then
|
|
echo "⚠️ [Memory Junction] $FAILED 개 해시 폴더 연결 실패 — Degraded 모드. 관리자 권한 setup 재실행 권장" >&2
|
|
fi
|
|
|
|
exit 0
|