diff --git a/.claude-plugin/install.sh b/.claude-plugin/install.sh index 1d8c7ce..1235a54 100755 --- a/.claude-plugin/install.sh +++ b/.claude-plugin/install.sh @@ -58,7 +58,12 @@ echo " [ok] Marketplace: PresenceWith-Vync (local: $PROJECT_ROOT)" echo " [ok] Plugin: vync@PresenceWith-Vync enabled" echo " [ok] Env: VYNC_HOME=$PROJECT_ROOT" -# 3. Sync plugin cache via rsync (Claude Code copies symlinks to real dirs, so rsync is required) +# 3. Copy plugin commands to project-level .claude/commands/ (non-namespaced access) +mkdir -p "$PROJECT_ROOT/.claude/commands" +cp "$PROJECT_ROOT/commands/vync.md" "$PROJECT_ROOT/.claude/commands/vync.md" +echo " [ok] Project command: /vync (non-namespaced alias)" + +# 4. Sync plugin cache via rsync (Claude Code copies symlinks to real dirs, so rsync is required) VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$PROJECT_ROOT/.claude-plugin/plugin.json','utf8')).version)") CACHE_BASE="$CLAUDE_DIR/plugins/cache/PresenceWith-Vync/vync" @@ -90,7 +95,7 @@ rsync -a --delete \ "$PROJECT_ROOT/" "$CACHE_DIR/" echo " [ok] Cache synced: v$VERSION" -# 4. Update installed_plugins.json (Claude Code reads active version from here) +# 5. Update installed_plugins.json (Claude Code reads active version from here) INSTALLED="$CLAUDE_DIR/plugins/installed_plugins.json" node -e " const fs = require('fs'); @@ -112,7 +117,7 @@ fs.writeFileSync(path, JSON.stringify(data, null, 2)); " echo " [ok] installed_plugins.json: vync@PresenceWith-Vync v$VERSION" -# 5. Done +# 6. Done echo "" echo "[vync] Setup complete! Restart Claude Code to activate." echo "" diff --git a/.gitignore b/.gitignore index 835f82c..a8bc6cf 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,6 @@ server.log # Docs — archived session/design records docs/archive/ + +# Auto-generated by install.sh (non-namespaced plugin command alias) +.claude/commands/vync.md diff --git a/agents/vync-translator.md b/agents/vync-translator.md index 05bc5e2..5ed2662 100644 --- a/agents/vync-translator.md +++ b/agents/vync-translator.md @@ -14,8 +14,8 @@ permissionMode: bypassPermissions ## 핵심 규칙 1. **vync-editing skill이 자동 로드됩니다.** 참조 문서(references/)를 활용하세요. -2. **ID 생성**: `node ~/.claude/skills/vync-editing/scripts/generate-id.js ` -3. **검증**: Write/Edit 후 반드시 `node ~/.claude/skills/vync-editing/scripts/validate.js ` 실행. 에러 시 수정 후 재작성. (PostToolUse hook은 sub-agent에서 발동하지 않음) +2. **ID 생성**: `node "$VYNC_HOME/skills/vync-editing/scripts/generate-id.js" ` +3. **검증**: Write/Edit 후 반드시 `node "$VYNC_HOME/skills/vync-editing/scripts/validate.js" ` 실행. 에러 시 수정 후 재작성. (PostToolUse hook은 sub-agent에서 발동하지 않음) 4. **서버 열기**: 파일 작성 후 `node "$VYNC_HOME/bin/vync.js" open ` 실행 (idempotent). ## 시각화 판단 가이드 @@ -56,7 +56,7 @@ permissionMode: bypassPermissions 2. 해당 타입의 참조 문서 Read (mindmap.md / geometry.md+arrow-line.md) 3. ID 생성 → PlaitElement[] JSON 구성 (skill 규칙 준수) 4. .vync 파일 Write (기존 파일 있으면 Read 후 merge) -5. `node ~/.claude/skills/vync-editing/scripts/validate.js ` 실행. 실패 시 수정 후 재작성. +5. `node "$VYNC_HOME/skills/vync-editing/scripts/validate.js" ` 실행. 실패 시 수정 후 재작성. 6. 서버 열기 7. 스냅샷 생성: 작성한 .vync 내용을 `.lastread`에 Write 8. 반환: 무엇을 어떤 구조로 시각화했는지 요약 @@ -81,15 +81,17 @@ permissionMode: bypassPermissions 3. 맥락과 diff를 고려하여 수정 판단 + 실행 - 구조적 변경(이동/재배치): Write로 전체 교체 - 텍스트 수정/노드 추가: Edit로 부분 수정 -4. `node ~/.claude/skills/vync-editing/scripts/validate.js ` 실행. 실패 시 수정 후 재작성. +4. `node "$VYNC_HOME/skills/vync-editing/scripts/validate.js" ` 실행. 실패 시 수정 후 재작성. 5. 서버 열기 6. 스냅샷 갱신: 수정된 .vync 내용을 `.lastread`에 Write 7. 반환: 무엇을 어떻게 변경했는지 요약 ## Skill 로드 Fallback -Skill tool이 사용 불가한 경우, 직접 Read: -- `~/.claude/skills/vync-editing/SKILL.md` -- `~/.claude/skills/vync-editing/references/mindmap.md` -- `~/.claude/skills/vync-editing/references/geometry.md` -- `~/.claude/skills/vync-editing/references/arrow-line.md` +Skill tool이 사용 불가한 경우: +1. Bash로 `echo $VYNC_HOME` 실행하여 프로젝트 루트 경로 확인 +2. 그 경로를 대입하여 아래 파일을 Read: + - `$VYNC_HOME/skills/vync-editing/SKILL.md` + - `$VYNC_HOME/skills/vync-editing/references/mindmap.md` + - `$VYNC_HOME/skills/vync-editing/references/geometry.md` + - `$VYNC_HOME/skills/vync-editing/references/arrow-line.md` diff --git a/docs/plans/2026-03-13-plugin-path-fix.md b/docs/plans/2026-03-13-plugin-path-fix.md new file mode 100644 index 0000000..1af9c7e --- /dev/null +++ b/docs/plans/2026-03-13-plugin-path-fix.md @@ -0,0 +1,136 @@ +# Plugin 경로 하드코딩 수정 계획 + +**날짜**: 2026-03-13 +**브랜치**: feat/semantic-sync (또는 별도 브랜치) +**상태**: 구현 + 검증 완료 + +## 문제 + +플러그인 마켓플레이스 등록 이후, SKILL.md와 agents/vync-translator.md에 하드코딩된 `~/.claude/skills/vync-editing/...` 경로가 실제 파일 위치와 불일치: + +- **하드코딩 경로**: `~/.claude/skills/vync-editing/scripts/generate-id.js` +- **실제 위치**: `~/.claude/plugins/cache/PresenceWith-Vync/vync/0.1.0/skills/vync-editing/scripts/generate-id.js` +- **결과**: `MODULE_NOT_FOUND` (Bash), `Unknown skill: vync` (Skill tool은 `vync:vync` 필요) + +## 해결 방안: $VYNC_HOME 기반 하이브리드 접근 + +### 설계 원칙 + +| 컨텍스트 | 방법 | 이유 | +|---------|------|------| +| Bash 명령 (generate-id, validate) | `$VYNC_HOME/skills/...` | Shell이 env var 자동 확장 | +| Read tool fallback | `$VYNC_HOME/...` + "먼저 echo로 확인" 안내 | Read tool은 env var 미확장 → AI가 해석 | +| Skill 자동 로드 | `skills: vync-editing` frontmatter (변경 없음) | Claude Code가 플러그인 내부에서 해석 | + +### 기각한 대안 + +| 대안 | 기각 이유 | +|------|----------| +| 캐시 절대경로 (`~/.claude/plugins/cache/.../0.1.0/...`) | 버전 의존적, 버전 변경 시 깨짐 | +| install.sh sed 템플릿 (`__VYNC_HOME__` → 실제경로) | 비멱등, 캐시 파일 변조, 복잡도 증가 | +| 상대 경로 (`./scripts/...`) | Read tool은 절대경로 필요, skill 로드 시 working dir ≠ skill dir | + +## 수정 대상 (2 files, 12곳) + +### 1. `skills/vync-editing/SKILL.md` — 5곳 + +| Line | 변경 내용 | +|------|----------| +| 22 | `node ~/.claude/skills/...` → `node "$VYNC_HOME/skills/..."` | +| 32 | 동일 패턴 | +| 85 | validate.js 경로 동일 변경 | +| 89-90 | assets 경로: `~/.claude/skills/...` → `$VYNC_HOME/skills/...` | + +### 2. `agents/vync-translator.md` — 7곳 + +| Line | 변경 내용 | +|------|----------| +| 17 | generate-id.js 경로 | +| 18 | validate.js 경로 | +| 59 | Create 절차 validate.js | +| 84 | Update 절차 validate.js | +| 89-96 | Fallback 섹션: Read 전 `echo $VYNC_HOME` 단계 추가 | + +### 수정 불필요 + +- `hooks/hooks.json` — vync-editing 참조 없음 +- `commands/vync.md` — 이미 `$VYNC_HOME` 사용 중 +- `.claude-plugin/install.sh` — 이미 정상 + +## 리스크 분석 + +| 시나리오 | 리스크 | 비고 | +|---------|--------|------| +| 최초 npm install | Low | install.sh → settings.env 먼저 설정 → 다음 세션부터 가용 | +| Sub-agent Bash 호출 | **PoC 필요** | settings.env 전파 여부 실제 검증 필요 | +| Read tool fallback | **PoC 필요** | AI가 $VYNC_HOME → 절대경로 치환 가능한지 검증 | +| 플러그인 버전 변경 | None | $VYNC_HOME은 프로젝트 루트 → 버전 무관 | +| 프로젝트 이동 후 npm install | None | VYNC_HOME 자동 갱신 | +| 다중 Vync 체크아웃 | Medium | 마지막 install 기준 (현행과 동일한 제약) | + +--- + +## PoC 항목 (실행 전 검증 필수) + +### PoC-1: Sub-agent에서 $VYNC_HOME 접근 가능 여부 + +**목적**: vync-translator sub-agent의 Bash에서 `$VYNC_HOME`이 확장되는지 확인 +**방법**: +``` +Agent({ + subagent_type: "vync:vync-translator", + mode: "bypassPermissions", + prompt: "## 테스트\nBash로 `echo $VYNC_HOME` 실행 후 결과를 반환해줘." +}) +``` +**기대**: `/Users/presence/projects/Vync` 출력 +**실패 시 대안**: translator.md에 "메인 세션이 VYNC_HOME 값을 prompt에 포함" 패턴 추가 + +### PoC-2: Sub-agent에서 $VYNC_HOME 기반 스크립트 실행 + +**목적**: 실제 generate-id.js가 `$VYNC_HOME` 경로로 실행되는지 +**방법**: +``` +Agent({ + subagent_type: "vync:vync-translator", + mode: "bypassPermissions", + prompt: "## 테스트\nBash로 `node \"$VYNC_HOME/skills/vync-editing/scripts/generate-id.js\" 3` 실행 후 결과를 반환해줘." +}) +``` +**기대**: 3개 랜덤 ID 출력 +**실패 시 대안**: PoC-1 실패와 동일 + +### PoC-3: Read tool fallback 경로 해석 + +**목적**: Sub-agent가 "$VYNC_HOME/..." 텍스트를 보고 실제 절대경로로 Read할 수 있는지 +**방법**: +``` +Agent({ + subagent_type: "vync:vync-translator", + mode: "bypassPermissions", + prompt: "## 테스트\n1. Bash로 `echo $VYNC_HOME` 실행\n2. 그 결과를 사용하여 `$VYNC_HOME/skills/vync-editing/references/mindmap.md`를 Read\n3. 첫 3줄을 반환해줘." +}) +``` +**기대**: mindmap.md 첫 3줄 (`# Mindmap Elements...`) 반환 +**실패 시 대안**: fallback 섹션을 "Bash에서 `cat $VYNC_HOME/skills/.../mindmap.md`" 방식으로 변경 + +### PoC 순서 + +PoC-1 → (통과 시) PoC-2 → (통과 시) PoC-3 +- PoC-1 실패 시: 대안 검토 후 계획 수정 +- 전체 통과 시: 본 수정 실행 + +## 검증 결과 (2026-03-13) + +### PoC 결과: 3/3 PASS +| # | 결과 | 비고 | +|---|------|------| +| PoC-1 | **PASS** | `echo $VYNC_HOME` → `/Users/presence/projects/Vync` | +| PoC-2 | **PASS** | generate-id.js 5개 ID + validate.js OK | +| PoC-3 | **PASS** | `echo $VYNC_HOME` → Read tool 절대경로 치환 → mindmap.md 정상 읽기 | + +### E2E 검증 (새 세션): PASS +- 새 Claude Code 세션에서 `/vync create` 호출 +- translator sub-agent가 `$VYNC_HOME` 기반 generate-id.js, validate.js 정상 실행 +- .vync 파일에 마인드맵 JSON 작성 + 요약 반환 확인 +- `Skill(vync)` → `Unknown skill` (네임스페이스 필요: `vync:vync`) — 별도 이슈, 경로 수정과 무관 diff --git a/skills/vync-editing/SKILL.md b/skills/vync-editing/SKILL.md index 4140839..fe3dd1b 100644 --- a/skills/vync-editing/SKILL.md +++ b/skills/vync-editing/SKILL.md @@ -19,7 +19,7 @@ description: Edit .vync canvas files (PlaitElement JSON). Use when creating or m `idCreator(5)` — 5-char random string from: `ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz` All IDs must be unique across the entire file (including nested children). -Generate with: `node ~/.claude/skills/vync-editing/scripts/generate-id.js [count]` +Generate with: `node "$VYNC_HOME/skills/vync-editing/scripts/generate-id.js" [count]` ## Editing Workflow @@ -29,7 +29,7 @@ Generate with: `node ~/.claude/skills/vync-editing/scripts/generate-id.js [count - Geometry (shapes): `references/geometry.md` - Arrow lines: `references/arrow-line.md` - Coordinate system: `references/coordinates.md` -3. **Generate IDs** using `node ~/.claude/skills/vync-editing/scripts/generate-id.js ` +3. **Generate IDs** using `node "$VYNC_HOME/skills/vync-editing/scripts/generate-id.js" ` 4. **Create** valid PlaitElement[] JSON following the reference 5. **Write** to file — PostToolUse hook will auto-validate @@ -82,9 +82,9 @@ Generate with: `node ~/.claude/skills/vync-editing/scripts/generate-id.js [count ## Validation Files are auto-validated by PostToolUse hook on Write/Edit. -Manual check: `node ~/.claude/skills/vync-editing/scripts/validate.js ` +Manual check: `node "$VYNC_HOME/skills/vync-editing/scripts/validate.js" ` ## Example Files -- `~/.claude/skills/vync-editing/assets/mindmap.vync` — 3-level mindmap -- `~/.claude/skills/vync-editing/assets/flowchart.vync` — 3 shapes + 2 arrows +- `$VYNC_HOME/skills/vync-editing/assets/mindmap.vync` — 3-level mindmap +- `$VYNC_HOME/skills/vync-editing/assets/flowchart.vync` — 3 shapes + 2 arrows