memory-layer-mcp 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of memory-layer-mcp might be problematic. Click here for more details.
- hybrid_search/__init__.py +3 -0
- hybrid_search/_skills/bootstrap-wiki.md +150 -0
- hybrid_search/_skills/maintain.md +196 -0
- hybrid_search/_skills/rebuild-index.md +129 -0
- hybrid_search/_skills/save-wiki.md +65 -0
- hybrid_search/_skills/search.md +104 -0
- hybrid_search/_skills/setup-hybrid-search.md +115 -0
- hybrid_search/cli.py +5231 -0
- hybrid_search/codex_hooks.py +495 -0
- hybrid_search/config.py +448 -0
- hybrid_search/hooks.py +721 -0
- hybrid_search/index/__init__.py +0 -0
- hybrid_search/index/ast_chunker.py +1248 -0
- hybrid_search/index/callgraph.py +296 -0
- hybrid_search/index/conversation_indexer.py +283 -0
- hybrid_search/index/dag.py +961 -0
- hybrid_search/index/doc_chunker.py +223 -0
- hybrid_search/index/drift.py +71 -0
- hybrid_search/index/embedder.py +220 -0
- hybrid_search/index/module_synth.py +327 -0
- hybrid_search/index/modules.py +552 -0
- hybrid_search/index/pipeline.py +580 -0
- hybrid_search/index/scanner.py +635 -0
- hybrid_search/index/synthesizer.py +611 -0
- hybrid_search/index/transcript_source.py +506 -0
- hybrid_search/memory/__init__.py +9 -0
- hybrid_search/memory/cards.py +457 -0
- hybrid_search/memory/hook_runtime.py +286 -0
- hybrid_search/memory/integrity.py +447 -0
- hybrid_search/memory/qa_log.py +538 -0
- hybrid_search/memory/quality.py +96 -0
- hybrid_search/memory/reader.py +529 -0
- hybrid_search/memory/router.py +147 -0
- hybrid_search/memory/routing_template.py +218 -0
- hybrid_search/project.py +114 -0
- hybrid_search/search/__init__.py +0 -0
- hybrid_search/search/bm25.py +158 -0
- hybrid_search/search/conv_in_flight.py +164 -0
- hybrid_search/search/fusion.py +95 -0
- hybrid_search/search/in_flight.py +304 -0
- hybrid_search/search/modules_search.py +309 -0
- hybrid_search/search/orchestrator.py +1877 -0
- hybrid_search/search/snippet.py +85 -0
- hybrid_search/search/vector.py +202 -0
- hybrid_search/security.py +150 -0
- hybrid_search/server.py +221 -0
- hybrid_search/storage/__init__.py +0 -0
- hybrid_search/storage/db.py +1108 -0
- hybrid_search/storage/indexes.py +45 -0
- hybrid_search/storage/wiki.py +645 -0
- hybrid_search/tools/__init__.py +0 -0
- hybrid_search/tools/hybrid_search.py +136 -0
- hybrid_search/tools/index.py +65 -0
- hybrid_search/tools/projects.py +50 -0
- hybrid_search/tools/semantic_search.py +158 -0
- hybrid_search/tools/symbols.py +60 -0
- hybrid_search/tools/trace.py +297 -0
- hybrid_search/tools/wiki.py +212 -0
- hybrid_search/wiki_cleanup.py +178 -0
- memory_layer_mcp-0.5.0.dist-info/METADATA +773 -0
- memory_layer_mcp-0.5.0.dist-info/RECORD +64 -0
- memory_layer_mcp-0.5.0.dist-info/WHEEL +4 -0
- memory_layer_mcp-0.5.0.dist-info/entry_points.txt +3 -0
- memory_layer_mcp-0.5.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bootstrap-wiki
|
|
3
|
+
description: "프로젝트의 코드베이스를 분석하여 wiki 페이지를 자동 생성합니다. hybrid_search 인덱스 + MCP 도구를 활용하여 주요 모듈/기능별 wiki를 만듭니다."
|
|
4
|
+
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Agent, mcp__hybrid-search__hybrid_search
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Bootstrap Wiki
|
|
8
|
+
|
|
9
|
+
프로젝트의 코드베이스를 분석하여 `.hybrid-search/wiki/` 디렉토리에 wiki 페이지를 자동 생성합니다.
|
|
10
|
+
|
|
11
|
+
## 실행 절차
|
|
12
|
+
|
|
13
|
+
### 1. 인덱싱 완료 확인 (필수)
|
|
14
|
+
|
|
15
|
+
**인덱싱이 완료될 때까지 절대 Step 2로 넘어가지 말 것.**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
hybrid-search-mcp status
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
상태를 확인하고:
|
|
22
|
+
- 인덱스가 없거나 파일 수가 0이면 → 인덱싱 실행 후 **완료될 때까지 대기**
|
|
23
|
+
- 인덱스가 있지만 파일 수가 프로젝트 규모에 비해 너무 적으면 → `--force` 재인덱싱
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 인덱싱 실행 (완료까지 대기 — 백그라운드로 보내지 말 것)
|
|
27
|
+
hybrid-search-mcp index {project_root} --force
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**인덱싱이 "Done: +N added" 메시지를 출력할 때까지 다음 단계로 진행 금지.**
|
|
31
|
+
|
|
32
|
+
### 2. 페이지 목록 확정 (기계적, 판단 금지)
|
|
33
|
+
|
|
34
|
+
Step 2a: 디렉토리 스캔으로 페이지 목록 생성
|
|
35
|
+
```bash
|
|
36
|
+
ls {project_root}/
|
|
37
|
+
ls {project_root}/app/ 또는 src/ 또는 lib/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Step 2b: 디렉토리별 파일/하위폴더 수를 세어서 페이지 수를 결정한다.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
for dir in app services components hooks lib types database src; do
|
|
44
|
+
[ -d "{project_root}/$dir" ] && echo "$dir: $(find {project_root}/$dir -maxdepth 1 -type d | wc -l) subdirs, $(find {project_root}/$dir -maxdepth 2 -name '*.ts' -o -name '*.tsx' -o -name '*.py' | wc -l) files"
|
|
45
|
+
done
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**페이지 수 결정 규칙:**
|
|
49
|
+
|
|
50
|
+
1. **architecture.md** — 항상 1개
|
|
51
|
+
2. **작은 디렉토리 (하위폴더 5개 미만, 파일 10개 미만)** → 디렉토리당 1페이지
|
|
52
|
+
3. **중간 디렉토리 (하위폴더 5~15개)** → 도메인 그룹별 2~5페이지로 분리
|
|
53
|
+
4. **큰 디렉토리 (하위폴더 15개+)** → 하위폴더/도메인마다 개별 페이지
|
|
54
|
+
|
|
55
|
+
**최소 페이지 수 가이드라인:**
|
|
56
|
+
- 파일 100개 미만: 10~20페이지
|
|
57
|
+
- 파일 100~500개: 20~40페이지
|
|
58
|
+
- 파일 500개+: 40~80페이지
|
|
59
|
+
|
|
60
|
+
Step 2c: **목록을 사용자에게 보여주고 확인받은 후 진행**
|
|
61
|
+
|
|
62
|
+
### 3. Wiki 디렉토리 생성 + .gitignore
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
mkdir -p {project_root}/.hybrid-search/wiki
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`.gitignore`에 `.hybrid-search/` 추가 (없으면 생성).
|
|
69
|
+
|
|
70
|
+
### 4. 병렬 Agent로 페이지 동시 생성
|
|
71
|
+
|
|
72
|
+
확정된 목록을 Agent로 병렬 실행합니다. 한 메시지에 여러 Agent를 동시 호출.
|
|
73
|
+
|
|
74
|
+
각 Agent에게 전달할 프롬프트 템플릿:
|
|
75
|
+
```
|
|
76
|
+
프로젝트: {project_name} ({project_root})
|
|
77
|
+
Wiki 페이지 생성: {filename}.md
|
|
78
|
+
주제: {topic_description}
|
|
79
|
+
관련 디렉토리: {directory_path}
|
|
80
|
+
|
|
81
|
+
다음을 수행하세요:
|
|
82
|
+
1. hybrid_search MCP 도구로 "{topic_keywords}" 검색
|
|
83
|
+
2. Glob으로 {directory_path}/ 하위 파일 목록 확인
|
|
84
|
+
3. 핵심 파일 1-2개를 Read로 읽기
|
|
85
|
+
4. {project_root}/.hybrid-search/wiki/{filename}.md 작성
|
|
86
|
+
|
|
87
|
+
형식:
|
|
88
|
+
# {title}
|
|
89
|
+
> 마지막 업데이트: {today} | 상태: fresh
|
|
90
|
+
## 개요 (1-2줄)
|
|
91
|
+
## 핵심 파일 (backtick 경로 + 역할)
|
|
92
|
+
## 데이터 흐름 (가능하면 ASCII 다이어그램)
|
|
93
|
+
## 주의사항
|
|
94
|
+
|
|
95
|
+
작성 원칙: 200줄 이하, 코드 덤프 아님, 시그니처만, 경로는 실제 존재하는 파일만.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
한 번에 최대 5개 Agent 병렬 실행. 5개 초과 시 배치로 나누기.
|
|
99
|
+
|
|
100
|
+
### 5. 병렬 완료 후: index.md 생성
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
# Wiki Index
|
|
104
|
+
|
|
105
|
+
> 프로젝트: {name} | 페이지: {count}개 | 생성: {YYYY-MM-DD}
|
|
106
|
+
|
|
107
|
+
## 페이지 목록
|
|
108
|
+
- [architecture](architecture.md) -- 전체 아키텍처 개요
|
|
109
|
+
- [{module}]({module}.md) -- {1줄 설명}
|
|
110
|
+
|
|
111
|
+
## 커버리지 gap
|
|
112
|
+
{아직 wiki가 없는 디렉토리/모듈 목록}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 6. DB 동기화 (필수)
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
hybrid-search-mcp sync-wiki --cwd {project_root}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 7. CLAUDE.md 연동
|
|
122
|
+
|
|
123
|
+
프로젝트의 CLAUDE.md에 `<!-- hybrid-search -->` 마커 추가.
|
|
124
|
+
|
|
125
|
+
### 8. post-commit hook 설치
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
hybrid-search-mcp install-hook --cwd {project_root}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 9. 검수 Agent 실행 (필수)
|
|
132
|
+
|
|
133
|
+
누락된 파일이 있으면 해당 파일만 추가 Agent로 생성합니다.
|
|
134
|
+
|
|
135
|
+
### 10. 최종 결과 보고
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
Wiki Bootstrap 완료
|
|
139
|
+
- 확정 목록: N개
|
|
140
|
+
- 생성 완료: N개 (100%)
|
|
141
|
+
- DB 동기화: N개
|
|
142
|
+
- CLAUDE.md 연동: 완료
|
|
143
|
+
- post-commit hook: 설치됨
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 주의사항
|
|
147
|
+
|
|
148
|
+
- Step 2의 페이지 목록을 100% 생성할 때까지 완료 보고 금지
|
|
149
|
+
- wiki 생성 전 반드시 hybrid_search 인덱스가 최신인지 확인
|
|
150
|
+
- Step 6(sync-wiki)를 건너뛰면 staleness 추적이 작동하지 않음
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maintain
|
|
3
|
+
description: "hybrid-search 인덱스와 wiki를 유지보수합니다. delta reindex + stale wiki 갱신(LLM synthesis 자동 실행) + wiki gaps 생성 + CLAUDE.md 최신화."
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Maintain — 일상 유지보수
|
|
8
|
+
|
|
9
|
+
검색과 분리된 유지보수 스킬. delta reindex + synthesis 자동화 + wiki gaps를 한 번에 처리한다.
|
|
10
|
+
인덱스 자체가 깨졌거나 불일치가 의심되면 `/rebuild-index`를 대신 사용할 것.
|
|
11
|
+
|
|
12
|
+
**핵심 원칙**: post-commit hook이 `reindex --synthesize`를 자동 실행하므로
|
|
13
|
+
`_synthesis_input/*.md`는 이미 쌓여있을 수 있다. 이 스킬은 거기서부터 이어받아
|
|
14
|
+
**LLM synthesis → finalize**까지 자동으로 돌린다.
|
|
15
|
+
|
|
16
|
+
**needs_synthesis flag 관리**: 이 스킬이 Step 2 → Step 4를 완료하면
|
|
17
|
+
`.hybrid-search/needs_synthesis` flag가 자동으로 사라진다. Step 2의 reindex는
|
|
18
|
+
stale이 0이면 flag를 제거하고, Step 4의 finalize는 합성 후 남은 stale을 기준으로
|
|
19
|
+
flag를 갱신하거나 삭제한다. 수동으로 지울 필요 없음.
|
|
20
|
+
|
|
21
|
+
## Step 1: 상태 확인
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
25
|
+
# hybrid-search-mcp 파이썬 경로: setup이 기록한 MCP 등록에서 읽는다.
|
|
26
|
+
VENV=$(python3 -c "import json,pathlib;print(json.load(open(pathlib.Path.home()/'.claude.json'))['mcpServers']['hybrid-search']['command'])" 2>/dev/null)
|
|
27
|
+
if [ -z "$VENV" ]; then
|
|
28
|
+
for dir in ~/project/claude_project/hybrid-search-mcp ~/projects/hybrid-search-mcp ~/hybrid-search-mcp; do
|
|
29
|
+
[ -f "$dir/.venv/bin/python" ] && VENV="$dir/.venv/bin/python" && break
|
|
30
|
+
done
|
|
31
|
+
fi
|
|
32
|
+
"$VENV" -m hybrid_search.cli status --cwd "$PROJECT_ROOT"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Step 2: Delta Reindex + Synthesis Prepare
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
"$VENV" -m hybrid_search.cli reindex --synthesize --cwd "$PROJECT_ROOT"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- 변경된 파일만 재인덱싱 (delta)
|
|
42
|
+
- stale wiki 감지 → `_synthesis_input/*.md` 자동 생성
|
|
43
|
+
- hook이 이미 돌렸으면 "no changed files"로 빠르게 끝남
|
|
44
|
+
|
|
45
|
+
## Step 3: Synthesis 병렬 실행 (신규 — Sonnet 에이전트)
|
|
46
|
+
|
|
47
|
+
`.hybrid-search/wiki/_synthesis_input/`에 `.md` 파일이 있으면 **Sonnet 에이전트를 모듈당 1개씩 병렬 spawn**한다.
|
|
48
|
+
|
|
49
|
+
### 3-1. input 파일 목록 확인
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
ls "$PROJECT_ROOT/.hybrid-search/wiki/_synthesis_input/"*.md 2>/dev/null
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
파일이 없으면 Step 4로 건너뜀.
|
|
56
|
+
|
|
57
|
+
### 3-2. 병렬 Agent 호출
|
|
58
|
+
|
|
59
|
+
input 파일 각각에 대해 Agent를 **한 메시지에 병렬로** 호출한다.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Agent({
|
|
63
|
+
description: "Synthesize wiki: <module>",
|
|
64
|
+
subagent_type: "general-purpose",
|
|
65
|
+
model: "sonnet",
|
|
66
|
+
prompt: <아래 템플릿>
|
|
67
|
+
})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**에이전트 프롬프트 템플릿** (파일마다 경로만 교체):
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
다음 hybrid-search wiki synthesis 작업을 수행해줘.
|
|
74
|
+
|
|
75
|
+
[입력 파일] <ABSOLUTE_PATH>/.hybrid-search/wiki/_synthesis_input/<module>.md
|
|
76
|
+
[출력 파일] <ABSOLUTE_PATH>/.hybrid-search/wiki/_synthesis_output/<module>.md
|
|
77
|
+
|
|
78
|
+
작업 절차:
|
|
79
|
+
1. 입력 파일을 Read로 읽는다. 파일에는 이미 아래가 포함되어 있다:
|
|
80
|
+
- SYNTHESIS_INSTRUCTIONS (반드시 따를 규칙)
|
|
81
|
+
- Deterministic Wiki (구조 데이터 — 절대 부정하지 말 것)
|
|
82
|
+
- Source Code (실제 코드 청크)
|
|
83
|
+
- Related Module Summaries
|
|
84
|
+
2. 입력 파일 안의 "Rules"와 "Output ONLY these sections" 지시를 그대로 따른다.
|
|
85
|
+
3. 결과물(## Overview, ## Key Design Decisions, ## Data Flow, ## Caveats, ## Related Modules만)을
|
|
86
|
+
출력 파일에 Write로 저장한다. 제목(# ...)이나 metadata는 포함하지 않는다.
|
|
87
|
+
4. 파일:라인 인용(`file.py:L42`)은 입력 파일의 Source Code 섹션에 실제로 나온 것만 사용한다.
|
|
88
|
+
존재하지 않는 심볼이나 파일은 인용하지 않는다 (verify가 제거함).
|
|
89
|
+
5. 기존 wiki의 언어(한국어 / 영어)를 그대로 유지한다.
|
|
90
|
+
|
|
91
|
+
완료되면 간단히 "done: <module>" 만 보고. 추가 설명 불필요.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**병렬 실행 예시** (input 파일 3개가 있으면):
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
메시지 하나에 Agent 호출 3개를 담아 보낸다.
|
|
98
|
+
subagent_type="general-purpose", model="sonnet".
|
|
99
|
+
description은 "Synthesize wiki: <module-name>" 형태로 각기 다르게.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
input 파일이 많으면(5개 초과) 최대 5개씩 batch로 묶어 순차 병렬 실행한다.
|
|
103
|
+
모든 에이전트 완료까지 기다린 후 Step 3-3으로 진행.
|
|
104
|
+
|
|
105
|
+
### 3-3. Output 파일 존재 확인
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
ls "$PROJECT_ROOT/.hybrid-search/wiki/_synthesis_output/"*.md 2>/dev/null
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
에이전트 하나라도 실패해서 output이 빠져있으면 해당 모듈만 재시도(다시 Agent spawn).
|
|
112
|
+
|
|
113
|
+
## Step 4: Finalize (검증 + DB 병합)
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
"$VENV" -m hybrid_search.cli synthesize-wiki --finalize --cwd "$PROJECT_ROOT"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- `_synthesis_output/*.md`를 읽어 `verify_references`(존재하지 않는 파일:라인 제거) + `verify_symbols` 실행
|
|
120
|
+
- `merge_synthesis_with_structure`로 deterministic wiki와 병합
|
|
121
|
+
- DB `wiki_pages` 업데이트 + `_raw/<module>.raw.md` 백업
|
|
122
|
+
- input/output 파일 자동 정리
|
|
123
|
+
|
|
124
|
+
## Step 5: 안전망 — verify + auto-fix
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
"$VENV" -m hybrid_search.cli verify-synthesis --fix --cwd "$PROJECT_ROOT"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
병합된 wiki에서 잔존 bad refs를 한 번 더 제거.
|
|
131
|
+
|
|
132
|
+
## Step 6: Wiki Gaps 채우기
|
|
133
|
+
|
|
134
|
+
`.hybrid-search/wiki-gaps.txt`가 있으면:
|
|
135
|
+
|
|
136
|
+
1. gap 목록 확인 — wiki가 없는 모듈/디렉토리
|
|
137
|
+
2. 중요도 판단: 파일 3개 이상인 디렉토리만 대상
|
|
138
|
+
3. `/bootstrap-wiki`와 동일한 형식으로 새 wiki 페이지 생성
|
|
139
|
+
4. `index.md` 갱신
|
|
140
|
+
|
|
141
|
+
gap이 3개 이상이면 Sonnet Agent 병렬로 생성.
|
|
142
|
+
|
|
143
|
+
## Step 7: DB 동기화 (gaps 생성 시에만)
|
|
144
|
+
|
|
145
|
+
gap으로 새 wiki를 만들었으면:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
"$VENV" -m hybrid_search.cli sync-wiki --cwd "$PROJECT_ROOT"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
finalize는 이미 DB에 썼으니 이 단계는 gap 생성 시에만 필요.
|
|
152
|
+
|
|
153
|
+
## Step 8: CLAUDE.md 확인
|
|
154
|
+
|
|
155
|
+
프로젝트의 CLAUDE.md에 `<!-- hybrid-search -->` 마커가 있는지 확인.
|
|
156
|
+
- 있으면: 의도 기반 라우팅 표가 최신인지 확인
|
|
157
|
+
- 없으면: 새 라우팅 표 삽입
|
|
158
|
+
|
|
159
|
+
## Step 9: Confidence 재캘리브레이션 (인덱스가 크게 변했을 때만)
|
|
160
|
+
|
|
161
|
+
reindex 결과가 대규모(변경 파일이 수백 개 이상, 또는 force rebuild 직후)이면
|
|
162
|
+
confidence 임계값이 새 점수 분포와 어긋날 수 있다. 프로젝트용 gold 배터리가
|
|
163
|
+
있으면 재캘리브레이션한다:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# 배터리 탐색: 프로젝트 로컬 → hybrid-search-mcp 레포 순.
|
|
167
|
+
HSDIR=$(dirname "$(dirname "$(dirname "$VENV")")")
|
|
168
|
+
GOLD="$PROJECT_ROOT/.hybrid-search/router_gold.json"
|
|
169
|
+
[ -f "$GOLD" ] || GOLD=$(ls "$HSDIR"/benchmarks/router_calibration/*_gold.json 2>/dev/null | head -1)
|
|
170
|
+
[ -n "$GOLD" ] && "$VENV" -m hybrid_search.cli recalibrate \
|
|
171
|
+
--cwd "$PROJECT_ROOT" --gold "$GOLD"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
- `strong_score`/`weak_score`/`strong_gap` 백분위와 `cosine_anchor`(중앙값)를
|
|
175
|
+
`~/.hybrid-search/config.toml`에 갱신한다.
|
|
176
|
+
- 배터리는 실제 사용자가 칠 법한 탐색형 질문이어야 함 — 쉬운 쿼리만 모으면
|
|
177
|
+
임계값이 과대해져 false-weak이 늘어난다.
|
|
178
|
+
- 소규모 delta reindex 후에는 건너뛴다 (분포가 거의 안 변함).
|
|
179
|
+
|
|
180
|
+
## 결과 보고
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
Maintain 완료
|
|
184
|
+
- Reindex: +N added, ~N changed, -N deleted
|
|
185
|
+
- Synthesis: N개 모듈 LLM 갱신 (Sonnet 병렬)
|
|
186
|
+
- Finalize: N개 병합, K bad refs 제거
|
|
187
|
+
- Wiki gaps: N개 생성
|
|
188
|
+
- CLAUDE.md: OK
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 주의사항
|
|
192
|
+
|
|
193
|
+
- **Sonnet 모델 고정**: synthesis 작업은 Opus가 아니라 Sonnet으로. 컨텍스트 격리 + 속도 이득.
|
|
194
|
+
- **에이전트 병렬 호출은 단일 메시지**: Agent tool 호출 여러 개를 한 메시지에 담아야 실제로 병렬 실행됨.
|
|
195
|
+
- **finalize가 verify를 자동 수행**: 에이전트가 환각 ref를 써도 CLI가 제거하니 관대하게 가도 됨. 단 너무 많으면 재시도.
|
|
196
|
+
- **실패 모듈만 재시도**: output 파일이 없는 모듈만 Agent 재spawn. 전체 재실행 금지.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rebuild-index
|
|
3
|
+
description: "인덱스 손상/불일치 시 복구. 상태 진단 → 불일치면 force rebuild, 아니면 delta reindex → 결과 검증."
|
|
4
|
+
allowed-tools: Bash, Read
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Rebuild Index — 인덱스 복구
|
|
8
|
+
|
|
9
|
+
인덱스에 문제가 있을 때 사용하는 **복구 전용** 스킬.
|
|
10
|
+
`/maintain`이 일상 유지보수(delta reindex + wiki 갱신)라면, `/rebuild-index`는 인덱스 자체가 깨졌을 때 쓴다.
|
|
11
|
+
|
|
12
|
+
## 역할 구분
|
|
13
|
+
|
|
14
|
+
| 스킬 | 용도 | 비용 |
|
|
15
|
+
|------|------|------|
|
|
16
|
+
| `/maintain` | 일상 유지보수 — delta reindex + stale wiki + gaps 채우기 | 낮음 (변경분만) |
|
|
17
|
+
| `/rebuild-index` | 인덱스 복구 — 손상/불일치 진단 + 필요시 full rebuild | 높음 (전체 재임베딩) |
|
|
18
|
+
|
|
19
|
+
## 언제 사용하는가
|
|
20
|
+
|
|
21
|
+
- 검색 결과가 이상하거나 인덱스 손상이 의심될 때
|
|
22
|
+
- ConsistencyMismatchError가 발생했을 때
|
|
23
|
+
- auto-rebuild가 실패해서 최신 변경이 미반영될 때
|
|
24
|
+
- embedding 설정이나 chunking 로직이 변경된 후
|
|
25
|
+
|
|
26
|
+
## Step 1: 상태 진단
|
|
27
|
+
|
|
28
|
+
현재 프로젝트의 인덱스 상태와 3-store 일치 여부를 확인한다.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel)
|
|
32
|
+
# hybrid-search-mcp 파이썬 경로: setup이 기록한 MCP 등록에서 읽는다.
|
|
33
|
+
VENV=$(python3 -c "import json,pathlib;print(json.load(open(pathlib.Path.home()/'.claude.json'))['mcpServers']['hybrid-search']['command'])" 2>/dev/null)
|
|
34
|
+
if [ -z "$VENV" ]; then
|
|
35
|
+
for dir in ~/project/claude_project/hybrid-search-mcp ~/projects/hybrid-search-mcp ~/hybrid-search-mcp; do
|
|
36
|
+
[ -f "$dir/.venv/bin/python" ] && VENV="$dir/.venv/bin/python" && break
|
|
37
|
+
done
|
|
38
|
+
fi
|
|
39
|
+
"$VENV" -m hybrid_search.cli status --cwd "$PROJECT_ROOT"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
추가로 3-store chunk 수를 직접 비교한다:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
"$VENV" -c "
|
|
46
|
+
from hybrid_search.config import load_config
|
|
47
|
+
from hybrid_search.storage.indexes import get_project_dir, IndexPaths
|
|
48
|
+
from hybrid_search.storage.db import StoreDB
|
|
49
|
+
from hybrid_search.project import project_hash
|
|
50
|
+
import tantivy, usearch.index
|
|
51
|
+
from pathlib import Path
|
|
52
|
+
|
|
53
|
+
pid = project_hash(str(Path('$PROJECT_ROOT').resolve()))
|
|
54
|
+
config = load_config()
|
|
55
|
+
project_dir = get_project_dir(config.projects_dir, pid)
|
|
56
|
+
idx = IndexPaths(project_dir)
|
|
57
|
+
|
|
58
|
+
if not idx.store_db.exists():
|
|
59
|
+
print('인덱스 없음 — delta reindex로 충분')
|
|
60
|
+
else:
|
|
61
|
+
db = StoreDB(idx.store_db)
|
|
62
|
+
sqlite = db.get_chunk_count(pid)
|
|
63
|
+
db.close()
|
|
64
|
+
t = tantivy.Index.open(str(idx.tantivy_dir))
|
|
65
|
+
bm25 = t.searcher().num_docs
|
|
66
|
+
v = usearch.index.Index.restore(str(idx.vector_index))
|
|
67
|
+
vec = len(v)
|
|
68
|
+
print(f'SQLite={sqlite}, Tantivy={bm25}, USearch={vec}')
|
|
69
|
+
if sqlite == bm25 == vec:
|
|
70
|
+
print('일치 — force rebuild 불필요')
|
|
71
|
+
else:
|
|
72
|
+
print('불일치 — force rebuild 필요')
|
|
73
|
+
"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
사용자에게 결과를 보고한다.
|
|
77
|
+
|
|
78
|
+
## Step 2: 판단 분기
|
|
79
|
+
|
|
80
|
+
### 불일치 발견 → Force Rebuild
|
|
81
|
+
|
|
82
|
+
전체 파일을 다시 chunking + embedding한다.
|
|
83
|
+
- atomic rebuild로 실행되므로, 실패해도 기존 인덱스는 보존된다
|
|
84
|
+
- 파일 수에 따라 수 분~수십 분 소요된다
|
|
85
|
+
- OpenAI embedding API 비용이 발생한다
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
"$VENV" -m hybrid_search.cli reindex --force --cwd "$PROJECT_ROOT"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
파일이 500개 이상이면 백그라운드 실행을 권장한다.
|
|
92
|
+
|
|
93
|
+
### 불일치 없음 → Delta Reindex
|
|
94
|
+
|
|
95
|
+
변경된 파일만 재인덱싱한다. 비용이 훨씬 적다.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
"$VENV" -m hybrid_search.cli reindex --cwd "$PROJECT_ROOT"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 인덱스 자체가 없음 → 첫 인덱싱
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
"$VENV" -m hybrid_search.cli reindex --cwd "$PROJECT_ROOT"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Step 3: 결과 검증
|
|
108
|
+
|
|
109
|
+
rebuild/reindex 완료 후 상태를 다시 확인한다.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
"$VENV" -m hybrid_search.cli status --cwd "$PROJECT_ROOT"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
검증 항목:
|
|
116
|
+
- chunk 수가 합리적인지
|
|
117
|
+
- 에러 없이 완료되었는지
|
|
118
|
+
- 마지막 인덱싱 시간이 방금으로 갱신되었는지
|
|
119
|
+
- (force rebuild 한 경우) 3-store 일치 여부 재확인
|
|
120
|
+
|
|
121
|
+
결과를 사용자에게 보고한다.
|
|
122
|
+
|
|
123
|
+
## 주의사항
|
|
124
|
+
|
|
125
|
+
- force rebuild는 OpenAI embedding API 호출 비용이 발생한다
|
|
126
|
+
- 대형 프로젝트(1000+ 파일)는 수 분 이상 걸린다
|
|
127
|
+
- 실패해도 기존 인덱스는 유지된다 (atomic rebuild)
|
|
128
|
+
- 동시에 다른 reindex가 돌고 있으면 lock file 충돌 가능 — 먼저 확인할 것
|
|
129
|
+
- 단순히 최신 반영이 필요한 거면 `/maintain`을 사용할 것
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: save-wiki
|
|
3
|
+
description: "대화 중 분석한 내용을 wiki 페이지로 저장합니다. .hybrid-search/wiki/에 저장하고 index.md를 갱신합니다."
|
|
4
|
+
allowed-tools: Read, Write, Edit, Glob, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Save Wiki
|
|
8
|
+
|
|
9
|
+
대화 중 분석한 내용을 `.hybrid-search/wiki/` 디렉토리에 wiki 페이지로 저장합니다.
|
|
10
|
+
|
|
11
|
+
## 언제 사용하는가
|
|
12
|
+
|
|
13
|
+
- 사용자가 "이거 저장해", "wiki에 추가해", "나중에 참고" 등 요청할 때
|
|
14
|
+
- 복잡한 코드 분석을 마친 후 결과를 영구 보존하고 싶을 때
|
|
15
|
+
- 기존 wiki 페이지가 stale이라 업데이트가 필요할 때
|
|
16
|
+
|
|
17
|
+
## 실행 절차
|
|
18
|
+
|
|
19
|
+
### 1. 저장할 내용 결정
|
|
20
|
+
|
|
21
|
+
방금 대화에서 분석/설명한 내용을 기반으로:
|
|
22
|
+
- 제목 결정 (예: "인증 시스템", "학원비 결제 흐름")
|
|
23
|
+
- 파일명 결정 (예: `auth-system.md`, `tuition-billing.md`)
|
|
24
|
+
- 디스크에서 Glob으로 `.hybrid-search/wiki/*.md` 확인하여 중복 체크
|
|
25
|
+
|
|
26
|
+
### 2. Wiki 파일 작성
|
|
27
|
+
|
|
28
|
+
`{project_root}/.hybrid-search/wiki/{filename}.md` 에 작성합니다.
|
|
29
|
+
|
|
30
|
+
형식:
|
|
31
|
+
```markdown
|
|
32
|
+
# {제목}
|
|
33
|
+
|
|
34
|
+
> 마지막 업데이트: {YYYY-MM-DD} | 상태: fresh
|
|
35
|
+
|
|
36
|
+
## 개요
|
|
37
|
+
{1-2줄 요약}
|
|
38
|
+
|
|
39
|
+
## 핵심 파일
|
|
40
|
+
- `path/to/file.ts` -- 역할
|
|
41
|
+
|
|
42
|
+
## 상세
|
|
43
|
+
{분석 내용}
|
|
44
|
+
|
|
45
|
+
## 주의사항
|
|
46
|
+
{특이사항}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 3. index.md 갱신
|
|
50
|
+
|
|
51
|
+
`.hybrid-search/wiki/index.md`의 페이지 목록에 새 항목을 추가합니다.
|
|
52
|
+
기존 항목을 업데이트하는 경우 날짜만 갱신합니다.
|
|
53
|
+
|
|
54
|
+
### 4. DB 동기화
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
hybrid-search-mcp sync-wiki --cwd {project_root}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 작성 원칙
|
|
61
|
+
|
|
62
|
+
- 대화에서 분석한 내용을 정리하여 작성 (코드 복붙 아님)
|
|
63
|
+
- 파일 경로는 현재 존재하는 파일만
|
|
64
|
+
- 200줄 이하
|
|
65
|
+
- 다음 대화에서 이 wiki만 읽으면 검색 없이 이해할 수 있는 수준
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: search
|
|
3
|
+
description: "코드베이스를 검색합니다. 질문 의도에 따라 Wiki(구조)와 hybrid_search(디테일)를 병렬 실행하고, 부족하면 Grep/Read로 보충합니다."
|
|
4
|
+
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Agent, mcp__hybrid-search__hybrid_search
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Search — 의도 기반 병렬 검색
|
|
8
|
+
|
|
9
|
+
코드베이스를 검색하는 통합 스킬. 질문 유형을 판단하고 최적 경로로 검색한다.
|
|
10
|
+
|
|
11
|
+
**자동 주입:** Claude가 `Grep`/`Glob`을 호출하기 직전, 이 프로젝트에 `.hybrid-search/wiki/index.md`가 있으면 **PreToolUse 훅**이 wiki 우선 탐색을 리마인드한다 (`route_hook`, matcher=`Glob|Grep`). 구조/관계 질문에서 Wiki를 스킵하고 Grep으로 직행하는 경향을 바로잡기 위함.
|
|
12
|
+
|
|
13
|
+
## Step 0: needs_synthesis flag 체크 (선행)
|
|
14
|
+
|
|
15
|
+
검색 시작 전 `.hybrid-search/needs_synthesis` 존재 여부를 한 번만 확인한다. 파일이 있으면 최근 커밋으로 wiki가 stale 상태 → 검색 결과에 **오래된 wiki**가 섞일 수 있음을 사용자에게 고지한다.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
19
|
+
FLAG="$PROJECT_ROOT/.hybrid-search/needs_synthesis"
|
|
20
|
+
if [ -f "$FLAG" ]; then
|
|
21
|
+
cat "$FLAG"
|
|
22
|
+
fi
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- flag가 있으면: 답변 상단에 한 줄 경고 — "⚠ wiki가 stale입니다 (N개 모듈). `/maintain` 실행 후 재질문 권장." (stale_modules 중 상위 3개 미리 보여줘도 됨)
|
|
26
|
+
- 없으면: 조용히 진행. 다음 Step으로.
|
|
27
|
+
- **기능 차단 금지:** 경고만 하고 검색은 그대로 수행. 사용자가 급히 답을 원할 수 있음.
|
|
28
|
+
|
|
29
|
+
## CLI 단독 사용
|
|
30
|
+
|
|
31
|
+
Claude Code 없이도 터미널에서 바로 검색 가능:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
hybrid-search-mcp search "authentication flow"
|
|
35
|
+
hybrid-search-mcp search "인증 로직" --json
|
|
36
|
+
hybrid-search-mcp search "handleSubmit" --node-types function
|
|
37
|
+
hybrid-search-mcp search "schema migration" --file-pattern "*.sql"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Step 1: 의도 분류
|
|
41
|
+
|
|
42
|
+
사용자 질문을 아래 5가지 중 하나로 판단한다:
|
|
43
|
+
|
|
44
|
+
| 유형 | 신호 | 예시 |
|
|
45
|
+
|------|------|------|
|
|
46
|
+
| **구조/관계** | "누가 호출", 의존, 모듈 구조, 전체 그림 | "A가 B를 호출하나?" |
|
|
47
|
+
| **기능 탐색** | 자연어, 한국어, 넓은 기능 질문 | "문제 업로드 기능 설명해줘" |
|
|
48
|
+
| **정밀 조회** | 정확한 심볼명, 파일명, 에러 문자열 | "handleSubmit 어디?" |
|
|
49
|
+
| **설계/맥락** | "왜 이렇게", QA 히스토리, 계획 문서 | "스키마 왜 이래?" |
|
|
50
|
+
| **스키마/DB** | 마이그레이션, DDL, 테이블 구조 변화 | "problems 테이블 히스토리" |
|
|
51
|
+
|
|
52
|
+
## Step 2: 실행
|
|
53
|
+
|
|
54
|
+
### 구조/관계 질문
|
|
55
|
+
|
|
56
|
+
**병렬 실행:**
|
|
57
|
+
- Wiki: `.hybrid-search/wiki/index.md` Read → 관련 페이지 Read (콜그래프, 모듈 관계)
|
|
58
|
+
- hybrid_search: 동시에 시맨틱 검색 실행
|
|
59
|
+
|
|
60
|
+
두 결과를 합쳐서 답변. Wiki가 구조를 잡고 hybrid_search가 디테일을 채운다.
|
|
61
|
+
|
|
62
|
+
### 기능 탐색 질문
|
|
63
|
+
|
|
64
|
+
**병렬 실행:**
|
|
65
|
+
- hybrid_search: 시맨틱 검색 (1차, 코드+문서+계획 문서 크로스 도메인)
|
|
66
|
+
- Wiki: `.hybrid-search/wiki/index.md` Read → 관련 모듈 페이지 확인
|
|
67
|
+
|
|
68
|
+
hybrid_search 결과가 주축, Wiki는 호출 흐름 보충.
|
|
69
|
+
|
|
70
|
+
### 정밀 조회 질문
|
|
71
|
+
|
|
72
|
+
**Grep first:**
|
|
73
|
+
- Grep으로 정확한 심볼/문자열 검색
|
|
74
|
+
- 결과가 부족하거나 맥락이 필요하면 → hybrid_search 또는 Wiki 보충
|
|
75
|
+
|
|
76
|
+
### 설계/맥락 질문
|
|
77
|
+
|
|
78
|
+
**hybrid_search first:**
|
|
79
|
+
- hybrid_search로 설계 문서, QA 기록, 계획 문서 검색
|
|
80
|
+
- 관련 모듈 구조가 필요하면 → Wiki 보충
|
|
81
|
+
|
|
82
|
+
### 스키마/DB 질문
|
|
83
|
+
|
|
84
|
+
**hybrid_search first:**
|
|
85
|
+
- hybrid_search 호출 시 `file_pattern: "*.sql"` 또는 `node_types` 활용
|
|
86
|
+
- 부족하면 → Grep으로 마이그레이션 디렉토리 직접 탐색
|
|
87
|
+
|
|
88
|
+
## Step 3: 보충 (fallback)
|
|
89
|
+
|
|
90
|
+
1차에서 답이 부족하면 도구를 **바꾸지 말고 보충**한다:
|
|
91
|
+
- hybrid_search 결과 부족 → Wiki에서 콜그래프/모듈 관계 확인
|
|
92
|
+
- Wiki 결과 부족 → hybrid_search로 문서/코드 디테일 보충
|
|
93
|
+
- Grep 결과에 맥락 부족 → Read로 파일 전문 확인
|
|
94
|
+
|
|
95
|
+
## 운영 규칙
|
|
96
|
+
|
|
97
|
+
- **쿼리는 사용자의 자연어 문장을 그대로** 쓸 것 — 키워드 뭉치로 재작성 금지.
|
|
98
|
+
(예: "우리 환불 기능에 대해 알려줘" ⭕ / "환불 퇴원 refund 워크플로우 정산" ❌)
|
|
99
|
+
자연어 문장이 벡터 레인 매칭 품질이 더 좋고(실측: 같은 주제에서 문장은 mixed,
|
|
100
|
+
키워드 뭉치는 weak), 분류기가 bm25_weight를 자동 조정한다.
|
|
101
|
+
- Wiki `[[링크]]`가 있으면 따라갈 것
|
|
102
|
+
- hybrid_search는 한국어 자연어 질의 가능 (크로스 언어 검색)
|
|
103
|
+
- 심볼명 검색은 BM25가 자동으로 가중치 올림 (자동 감지)
|
|
104
|
+
- `file_pattern`으로 범위 좁히기 가능 (예: `*.ts`, `migrations/*.sql`)
|