Repository navigation
Releases: cookyman74/llmwiki-harness
Release list
v0.11.0 — llmwiki MCP 서버 (npm obsidian-llmwiki-mcp@0.1.0)
v0.11.0 — llmwiki MCP 서버 (npm obsidian-llmwiki-mcp@0.1.0)
상태(2026-09-11): npm
obsidian-llmwiki-mcp@0.1.0공개 완료 — P0~P4 전부 포함. 레지스트리 shasum15eb8eeb…= main5c72f90. 이 문서가git tag v0.11.0(2026-09-11) 의 릴리즈 노트다. 원안 이름llmwiki-mcp는 npm 유사도 정책으로 거부되어 바꿨고, 실행 명령은 그대로llmwiki-mcp다.이전 상태: 초안 — 배포 차단. P3 외부리뷰(2026-09-09, codex)가 "배포 불가"로 판정했고 그 사유가 아래 "배포 전 남은 조건"에 있다.
npm publish와git tag v0.11.0은 그 조건 해소 + 사용자 승인 후에만 진행한다(P3-08·P3-23).
무엇이 생겼나
볼트 안 Claude Code만 쓰던 위키 리트리벌을 MCP stdio 서버로 노출했다. Codex CLI·Gemini CLI·agy·Cursor·Windsurf·Claude Desktop·VS Code, 그리고 직접 만든 MCP 클라이언트가 같은 위키를 읽는다. 설치는 등록 한 줄이고 사전 설치물은 Node ≥20 하나뿐이다.
npx obsidian-llmwiki-mcp print-config --client codex --root /path/to/llmwiki.obsidian # 등록 스니펫 생성도구 4개: wiki_expand(진입점 — seed→관계 1홉→MoC, 옵션 BM25 rerank) · wiki_pack(claims·confidence·status·관계 팩) · wiki_read_page(전문 read) · wiki_search(fallback). 읽기 전용이며 파일링·인제스트·lint는 볼트 자체 하네스가 계속 담당한다.
구조
| 계층 | 내용 |
|---|---|
| 정본 | .claude/skills/wiki-lint/scripts/{search,scope-expand}.py — A/B 5라운드로 검증된 랭킹 규칙 |
| 포팅 | tools/llmwiki-mcp/src/*.ts — 같은 규칙의 TypeScript 구현 |
| 보증 | tests/parity.py(골든셋)·tests/parity_fuzz.py(차등 퍼징) — 두 구현이 같은 출력을 내는지 CI가 검사 |
리트리벌 규칙을 바꾸면 Python·TS·픽스처 3점을 한 PR에서 함께 고친다.
검증 결과
| 항목 | 결과 |
|---|---|
| 단위 테스트 | 45파일 602건 통과 (공개 커밋 main 5c72f90, P4 포함). 참고: P3 끝 f098497 은 39파일 545건 |
| 패리티(픽스처 14질의 × 4모드) | FAIL 0 / GOLDEN DRIFT 0 |
| 패리티(실볼트 5질의 × 4모드) | 0/20 FAIL, 3회 반복 digest 동일 |
| 차등 퍼징 | 420/420 일치(seed 고정) |
| CI | smoke·parity × ubuntu·macOS·windows = 6/6 |
| 성능 | 실볼트 309페이지 그래프 구성 31~37ms · 합성 1,000페이지 50ms · MCP initialize 왕복 123ms · npx 콜드스타트 5.8s(캐시 비운 tarball 기준) |
클라이언트 실측 (P3)
| 클라이언트 | 등록 | 사실브리핑 라우팅 |
|---|---|---|
| Claude Code | claude mcp add 성공 |
준수 — wiki_expand → wiki_pack, 전문 read 0회, confidence 병기 |
| Codex CLI 0.153 | codex mcp add 성공 |
준수 — 사실 3/3 · 절차 2/2. 단 codex exec 는 기본 approval: never 라 MCP 도구가 차단되므로 비대화형에서는 --approve-for-me 가 필요하다 |
| agy 1.1 | agy mcp add 성공 |
미달 — 스니펫 설치 후에도 wiki_search→전문 read 를 선호(사실 0/3 · 절차 0/2). 1회 준수했으나 재현되지 않음 |
| Gemini CLI · Cursor · Windsurf · Claude Desktop · VS Code | 설정 스니펫을 실제 파일과 dry-merge로 검증 | 실사용 미확인(이 환경에 Gemini CLI 미설치, Cursor는 GUI) |
근거 로그는 develop_docs/v0.8.6/todo/evidence/(로컬 전용)에, 판정표는 같은 폴더 P3-routing.csv에 있다.
실측으로만 잡힌 것
- Codex 등록 명령이 실제로는 실패했다.
codex mcp add <name> -c mcp_servers.<name>.startup_timeout_sec=60 -- <cmd>는 "invalid transport"로 죽는다(-c가 command 없는 테이블을 먼저 만든다). 문자열 리뷰 3라운드가 놓쳤고 실행에서 드러났다. 플래그 없는 등록 +config.toml안내로 고쳤다. - 라우팅은 서버 설명만으로 완결되지 않는다. 같은 서버·같은 설명인데 클라이언트마다 도구 선택이 달랐다. 진입점을 도구 목록 앞으로 옮기고 fallback·최후수단 문구를 강화해 개선했고, 그래도 미달인 클라이언트는 규칙 스니펫으로 해결한다.
- Windows
%%이스케이프는 배치 파일 전용이다. 대화형 cmd.exe는 큰따옴표 안에서도%VAR%를 확장한다.%·!가 든 볼트 경로는 명령형 등록을 거부하고 JSON 설정형을 안내한다.
외부리뷰
P0~P2 각 단계마다 codex·agy 교차 리뷰를 돌렸고(총 10회), P3 리뷰는 1회(codex) 수행해 배포 불가 판정을 받았다 — 그 지적을 반영한 뒤 재리뷰가 필요하다. 검출·수정한 것 중 중요한 것: 볼트의 wiki 디렉터리가 심볼릭 링크일 때 외부 파일 유출, 구조화 응답이 200KB 상한을 우회, 읽기 전용 CI 가드의 별칭 import 우회, fmt1 거짓 tie, 이중 BOM, Python과 Node의 Unicode 버전 차이 55 코드포인트. 리뷰 원문과 판정표는 develop_docs/v0.8.6/todo/review/ 와 각 단계 문서에 있다.
알려진 한계
macOS NFD 파일명과 NFC 질의가 어긋날 수 있다(Python 정본과 바이트 동일을 유지하려 정규화하지 않는다). 대소문자 무시 파일시스템에서는 다른 대소문자 slug가 해석될 수 있다. wiki/ 안 심볼릭 링크는 건너뛴다. 클라우드 온디맨드 파일은 첫 read가 느리다. stdio 전용이며 HTTP는 없다. 그래프는 호출마다 재구성한다(캐시는 P4).
알려진 미충족 조건 (P3 외부리뷰 판정 — 사용자 결정으로 한계로 두고 공개)
- 라우팅 지표 미달 — 15회 측정 결과 Claude Code 5/5 · Codex 5/5 · agy 0/5(합계 10/15). 서버 결함이 아니라 agy 의 도구 선택 특성이다. 지표를 "CLI 3종 모두 준수"로 유지할지, "2종 준수 + agy 는 알려진 한계"로 조정할지 결정이 필요하다.
- 필수 클라이언트 5종 중 2종 미검증 — 이 환경에 Gemini CLI가 없고 Cursor는 GUI다. 설정 스니펫은 실제 파일과 dry-merge로만 확인했다.
Codex 재현성— 해소됐다. 원인은codex exec의 기본approval: never였고--approve-for-me로 5/5 준수를 확인했다. README·클라이언트 가이드에 조건을 명시했다.- Windows 실셸 미검증 — 등록 스니펫의 문법은 단위 테스트로 고정했지만 cmd.exe·PowerShell에서 실제 등록은 확인하지 못했다.
그 밖에 남은 작업
— 2026-09-11 완료.npm publishnpx -y obsidian-llmwiki-mcp@0.1.0콜드 2.82s·웜 0.9s 로 재검증— 2026-09-11 완료(주석 태그 + GitHub Release)git tag v0.11.0- 구조화 출력: 0.1.0 은 기본 텍스트만이다. structuredContent·outputSchema 가 필요한 클라이언트는 서버 환경에
LLMWIKI_STRUCTURED=1을 넣는다(첫 공개라 호환성 변경 아님). - P4: 프로세스 내 mtime 캐시·텍스트 전용 기본값 — 0.1.0 에 포함되어 공개됐다(서버 2회차 호출 1,000p 164→26ms, 모델 입력 2~4배 → 1배).
v0.10.0 — 음성 녹음 → 회의록 (로컬/OpenAI 이중 백엔드)
녹음 파일을 전사해 회의록으로 남기는 파이프라인을 추가한다. 하네스가 텍스트 소스만 다루던 범위를 음성으로 넓힌다.
추가
| 구성요소 | 역할 |
|---|---|
meeting-minutes 스킬 |
녹음 → 전사 → 회의록 워크플로우 + 민감도 판정표 |
meeting-scribe 에이전트 |
전사문 → 결정·액션·미결 구조화 (sonnet) |
transcribe.py |
로컬(mlx-whisper) / OpenAI 이중 백엔드 |
apikey.py |
키 해석 · macOS 키체인 저장 · 인증 테스트 |
에이전트 5 → 6, 스킬 6 → 8(문서에 누락돼 있던 weekly-review 포함), 스크립트 10 → 12.
핵심 — 외부 전송을 코드로 막는다
이 스킬은 다른 스킬과 성격이 하나 다르다. 오디오를 외부로 보낼지 말지라는 되돌릴 수 없는 결정을 포함한다.
| 회의 성격 | 백엔드 |
|---|---|
| 인사·평가·심사·계약·개인정보·보안·고객사 기밀 | 로컬 (온디바이스) |
| 일반 업무회의·기술 논의·일정 조율·사내 세미나 | OpenAI API |
애매하면 로컬. 오분류 비용이 비대칭이다 — 로컬 오분류는 시간만 더 들지만, OpenAI 오분류는 되돌릴 수 없다(삭제해도 캐시·색인이 남을 수 있다).
이 규칙을 SKILL.md에만 두면 잊힌다. 그래서 --confirm-upload 없이는 openai 백엔드가 실행 자체를 거부한다. 플래그를 붙이는 행위가 곧 판정을 마쳤다는 기록이 된다.
$ transcribe.py --backend openai --input 회의.m4a
openai 백엔드는 오디오를 외부 서버로 전송한다.
민감 회의(인사·평가·심사·계약·개인정보)라면 --backend local 을 쓰라.
exit=1 # 네트워크 호출 0회
산출물 분리
전사 원문(raw/meetings/transcripts/)과 회의록(raw/meetings/)을 나눈다. 63분 녹음은 2만 자를 넘어 회의록 가독성을 파괴하고 인제스트 토큰을 낭비한다. 원문은 근거로 보존하고 링크로만 참조하며, 회의록 작성은 meeting-scribe에 위임해 메인 컨텍스트 오염을 막는다.
키 관리
해석 순서: --api-key > OPENAI_API_KEY > macOS 키체인 > ~/.config/llmwiki/secrets.json(0600) > 레거시 파일.
키체인을 권하는 이유 — 암호화 저장이고, 환경변수로 자식 프로세스에 새지 않으며, 볼트가 클라우드 동기화돼도 따라가지 않는다.
사용
python3 .claude/skills/meeting-minutes/scripts/transcribe.py --check
python3 .claude/skills/meeting-minutes/scripts/apikey.py set-keychain
# 민감 회의
transcribe.py --backend local --input "raw/assets/녹음.m4a"
# 일반 회의 (판정 + 사용자 확인 후)
transcribe.py --backend openai --confirm-upload --input "raw/assets/녹음.m4a"평소에는 "녹음 정리해줘" 로 스킬이 트리거된다.
사전 요구
ffmpeg(brew install ffmpeg)- 로컬 백엔드:
pip install mlx-whisper(Apple Silicon) 또는faster-whisper - 첫 실행 시 모델 ~1.5GB 다운로드 (실측 4분 46초)
검증
- 실녹음 63분 2건 로컬 전사 (82블록 · 25,461자) → 회의록 생성 (결정 9 · 액션 7 · 미결 6)
- 업로드 차단 exit 1 · 네트워크 0회
- 특수문자 파일명 종단 테스트 통과
- 트리거 lint: should 6 / should-NOT 4
알려진 제약
화자 분리 미지원. Whisper 계열은 화자를 출력하지 않는다. meeting-scribe는 호명·자기소개·역할 명시 같은 근거가 있을 때만 발언을 귀속하고, 나머지는 화자 없이 기록한다 — 심사·평가 회의에서 잘못된 발언 귀속은 내용 누락보다 해롭다. WhisperX + pyannote 옵션은 후속 과제로 남긴다(7인 단일 마이크 조건에서 실측 정확도 60~80% 예상).
전문 링크: #17
v0.9.3 — raw 스탬프 정규화 + 값 검증
raw 인제스트 스탬프를 frontmatter 맨 위로 정규화(가시성·본문 immutable 유지) + ingest-status가 손상된 ingest_status 값(done/stale/pending 밖·제어문자)을 BAD로 조기 노출. normalize-stamps.py 신설·ingest-status.py 값검증. 외부감사(agy) 반영.
🤖 Generated with Claude Code
v0.9.2 — README 7.5 보강 (TECH-SUMMARY 정합)
README 질의 리트리벌 섹션에 팩관계(v0.8.6)·라우팅 파라미터표·교훈 2개·참고자료를 보강해 TECH-SUMMARY와 정합. BM25 공식·구현 상세는 TECH-SUMMARY 포인터로 유지.
🤖 Generated with Claude Code
v0.9.1 — README 질의 리트리벌 최적화 섹션
README에 질의 리트리벌 최적화(v0.8.4~v0.9.0) 섹션 7.5 추가 — 그래프확장+팩·질의유형 라우팅·BM25 rerank와 근거자료(GraphRAG·Parent-Document Retriever·Adaptive-RAG·Anthropic Contextual Retrieval), 실측표(사실 −55%·tool −93%).
🤖 Generated with Claude Code
v0.9.0 — weekly-review 스킬 + 일상 응용 가이드
질의 도구를 넘어 일상 업무 응용으로 확장(외부 PKM/LLM-wiki 사례 리서치 기반).
- weekly-review 스킬: 금요일 주간리뷰 자동화 — 완료·미결(open loops)·stale·다음주 우선순위를 라우팅+팩으로 종합해 query 페이지 파일링. 회고·계획·상급자 보고 초안.
- README 6.5 일상 응용 섹션: 회의(ADR·회의전 브리핑)·학습(신뢰도·망각 복습)·개발(트러블슈팅→L4 런북)·주간리뷰 매핑 + 이 위키만의 차별점 표.
예약: CronCreate는 세션 한정 → 영속 자동화는 OS cron/CI에서 claude -p '/weekly-review' 헤드리스.
🤖 Generated with Claude Code
v0.8.6 — 팩에 관계 포함 + 기술 종합 문서
관계중심 질의가 claims 팩에서 ## 관계·연결개념을 놓치던 문제 → 새 라우트 없이 팩에 관계 줄 추가(+300토큰). 관계질의=관계 실린 사실브리핑. 외부감사(agy) 반영(펜스 오포착 방지·claim 중복 제외).
develop_docs/v0.8.3/TECH-SUMMARY.md: v0.8.4~0.8.6 리트리벌 최적화를 근거자료(Adaptive-RAG·Parent-Document Retriever·Anthropic Contextual Retrieval·BM25·GraphRAG)와 함께 종합.
🤖 Generated with Claude Code
v0.8.5 — 질의유형 라우팅 + BM25 rerank (combo)
질의유형별 리트리벌 분기: 조회=seed / 사실브리핑=BM25 rerank11+claims팩 / 절차=후보 full-read.
A/B 5라운드 실측: 사실브리핑 22.7k/1read(광역 대비 −55%), 절차질의는 동률(스코핑 이득 없음 — 팩 오버헤드만 제거). rerank는 사실질의 최대 레버지만 다이얼(과하면 실항목 누락 → 11 균형).
리서치 근거: Adaptive-RAG·Parent-Document Retriever·Anthropic Contextual Retrieval. scope-expand.py --rerank(BM25 0토큰) 신설. 외부감사(agy) 반영.
🤖 Generated with Claude Code
v0.8.4 — 질의 리트리벌 최적화 (그래프확장 + claims 팩)
index.md 통독 폐지. lexical seed→관계 1홉(아웃·인·MoC멤버 Top-K) 그래프확장→claims 컨텍스트 팩. 순수 lexical이 관계연결 페이지에 못 닿던 recall 회귀를 그래프확장으로 복구.
A/B 4라운드 실측(동일조건): 토큰 −37%, tool_uses −64%(속도), recall 유지.
scope-expand.py 신설 + search.py --files + wiki-query/ops/synthesizer 배선. 외부감사(agy) 반영.
🤖 Generated with Claude Code
v0.8.3 — ingest-status 긴 frontmatter 스탬프 버그 수정
ingest-status.py가 앞 600바이트만 읽어, 긴 description 등으로 스탬프가 밀린 raw 파일을 PENDING으로 오인하던 버그 수정. frontmatter 블록 전체 파싱으로 변경. 외부감사(agy) 반영: 값 따옴표 허용 + 닫는 --- 없을 때 본문 오파싱 방지.
🤖 Generated with Claude Code