별칭을 줄별 개별 dense 벡터(sentinel `{chunk}#alias#N`)로 색인하고
boilerplate 청크는 별칭 생성을 skip. 묶음 1벡터 방식은 평균화로 특정
표현이 희석돼 오히려 회귀(13/18)했던 것을 폐기. 변형 일관성 14/18 →
16/18, mean_spread@10 0.222 → 0.111 (나무위키 ~1000 문서 CS corpus).
`kebab-core::strip_alias_suffix` 가 suffix 형과 per-alias 형 둘 다 처리.
파생물 캐시(V012): embedding 벡터 + 별칭 LLM 결과를 청크 내용 해시
키로 캐싱해 재색인 시 내용 불변 청크의 재계산을 skip. cache_key =
blake3(kind ‖ text_blake3 ‖ version_key)[:32], version_key 에
model/prompt/dimensions 포함 → §9 cascade 와 정합(버전 bump 시 자동
miss). 측정: 정답 3개 cold 1879s → warm 13s ≈ 145배. 순수 가산이라
corpus_revision bump 없음. search/ask 는 kebab.sqlite+lancedb 만으로
동작 → 외부 서버 색인 후 DB 만 복사하는 이식 워크플로 가능.
V012 schema migration + 신규 surface 로 workspace version 0.20.2 →
0.21.0 (minor) bump. README/HANDOFF/ARCHITECTURE/HOTFIXES sync.
known limitation: stack·svm 설명형 2개 잔존 + grounded 판정이 부분
인용을 grounded 로 오분류(후속 후보).
측정 상세: docs/superpowers/handoffs/2026-05-31-namu-wiki-alias-cache-study.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LanceDB 후보의 sentinel chunk_id({orig}#alias)는 chunks JOIN 에서 탈락해
VectorRetriever strip 이전에 사라진다. candidate 를 kebab_core::strip_alias_suffix
로 원본 chunk_id 로 strip 해 IN-list/JOIN 에 넣어(committed 판정은 원본 body chunk
기준) 통과시키되, 반환은 입력 candidate 형태(sentinel 유지) — VectorRetriever 가
그 sentinel 을 받아 strip+dedup 한다. SQL replace 대신 (b) Rust strip 채택(명확).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
별칭 dense 벡터를 sentinel chunk_id({orig}#alias)로 색인하려면 chunks 에 없는
chunk_id 가 embedding_records 에 들어가야 한다. V001 의 chunk_id REFERENCES chunks
ON DELETE CASCADE FK 가 이를 SQLite 787 로 막으므로 테이블을 FK 없이 재생성한다.
status/vector_committed(V003) + 3개 인덱스 보존, chunks_bd_tombstone_embeddings
trigger 무수정. DROP→RENAME 시 dangling trigger 재파싱을 피하려 legacy_alter_table=ON.
사라진 CASCADE 는 put_chunks + purge 두 경로(purge_orphan_at_workspace_path,
purge_deleted_workspace_path)의 명시 DELETE 로 대체 — chunks 삭제 직전 원본 +
{id}#alias sentinel embedding_records 를 함께 정리. corpus_revision baseline 2→3.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
별칭 dense 벡터({orig}#alias) hit 을 원본 chunk_id 로 strip 해 hydrate,
body+alias 중복은 첫(높은 score) 하나만 유지. overfetch 2→3 (dedup 후 k
확보). wire/RetrievalDetail 무변경. vector/hybrid 회귀 0, clippy green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Task 6 리뷰 MINOR-1: spec 본문이 단일 UNION ALL+GROUP BY 로 기술됐으나
shipped = 2-query(run_query+run_alias_query) + Rust merge_body_alias(body 우선).
서로 다른 FTS 테이블 bm25 절대값 비교가 무의미해 body-우선 merge 가 더 깨끗.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- M1: chunk_aliases trigger 가드에 AND aliases <> '' (빈 문자열 미색인)
- M2: 재색인 멱등 테스트 (재-put 후 별칭 행 1개)
- N1: 본문 격리 음성 단언 (별칭 term 이 chunks_fts 로 누출 안 됨)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brainstorm 확정: 청크당 별칭 생성(같은언어+한↔영 번역), additive+수동
재색인, 1차 단순 품질제어. 별도 FTS5 aliases 채널 → RRF 3채널 융합.
flag off 기본, kebab eval variants 로 on/off 측정.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
README 의 괴물 셀(ingest 2891→544, search 2952→687, ask 1244→415, tui 2300→453자)을
"무엇 + 핵심 flag + 포인터"로 축소. 빠진 구조 detail 은 ARCHITECTURE 로 이전:
- symbol path 형식에 Go/Java/Kotlin/C/C++ 추가 + code chunk provenance(citation.kind/code_lang/repo)
- Markdown title 자동 채움 순서(md-frontmatter-v2)
- RAG groundedness 검증(mDeBERTa-v3 XNLI, nli_threshold gate) 결정 행 신설
- TUI 행을 P9-1~4 완료 + F1 cheatsheet 로 최신화 (stale "진행 예정" 제거)
flag 망라는 --help, TUI 키는 in-app F1 cheatsheet(권위 런타임 소스)로 위임 — stale 방지.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
목표 재정의: 한/영 overlap → 같은 의미의 다양한 표현(동의어·다른 어휘·풀어쓴
문장·한영)에서 일관된 답변 품질. 지난 reranker 실험이 overlap 프록시 최적화로
헛돈 교훈 반영 — 처방 전 진짜 지표(변형 일관성)를 직접 재는 평가부터.
Phase 1(본 spec 구현): kebab-eval golden suite에 변형 그룹(intent group) +
변형 일관성 메트릭(recall_spread, answer_consistency) + recall@pool vs recall@k로
(A)순위출렁/(B)어휘격차 자동 판별. Phase 2(처방)는 측정 결과 게이트 뒤 조건부.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CLAUDE.md docs-split 규칙에 따라 사용자 visible surface 변경 동기화.
README:
- [rag] prompt_template_version default rag-v2 → rag-v3 (v0.20.2)
- v3 규칙 설명 (답변 언어 = 질문 언어)
- O-2 known limitation (소형 모델 refusal 언어 불일치)
HANDOFF:
- 머지 후 발견된 버그/결정 에 v0.20.2 1줄 요약 추가
- 검색 품질 baseline (hybrid MRR=0.833) + O-2 known limitation 언급
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.20.2 릴리즈 노트 초안 작성. 사용자 영향 4단락 구조로 각 finding 기술.
- Finding #1/O-2: rag-v3 응답언어 자동 매칭 + refusal 언어중립화
- Finding #2: bulk search input schema 확정 (15필드)
- Finding #3: list docs human-readable path 보강
- Finding #7: index_version 두 곳 구분 (vector vs FTS5)
- eval --config facade + 검색 품질 baseline (hybrid hit@3=1.0 / MRR=0.833)
- Finding #4/#5/#6/#8: docs/schema 정비
- version cascade 주의 (rag-v3 → eval compare)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8-finding 도그푸딩 라운드 및 검색 품질 baseline 결과를 HOTFIXES 에 기록.
- 8 findings 요약 표 (rag-v3, bulk schema, list docs, index_version 등)
- Finding O-2 known limitation (소형 모델 refusal 언어 불일치)
- 검색 품질 baseline 표 (hybrid MRR=0.833, lexical MRR=0.7)
- golden 큐레이션 교훈 (dispatch.py 정답 정정 → hit@3 0.9→1.0)
- eval logs cross-link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
eval --config facade 패치로 dogfood KB 직접 평가 가능해짐에 따라
§10 Eval 에 §10.2 검색 품질 baseline 섹션 추가.
- golden suite 실행 명령 (hybrid + lexical eval run → aggregate)
- v0.20.2 metric baseline 표 (hybrid hit@3=1.0 / MRR=0.833)
- 정성 체크리스트 (한국어 2자 hit@3, empty=0, MRR 임계치)
- golden 큐레이션 절차 + dispatch.py 오류 교훈
- §10.1 로 기존 basic eval run 재구성
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Incorporates all critic (opus) round-1 findings into the dogfood
search-quality eval design spec:
BLOCKER-1: §4.4 execution commands now use --config /build/dogfood/config.toml
(Task A facade-rule patch makes this the canonical path). §5.1 re-titled
from "(후속 패치)" to "Task A로 적용됨 — 권장 운영 경로"; XDG workarounds
demoted to "패치 전 fallback". Intro paragraph updated accordingly.
MAJOR-1: §3 Non-Goals gains an explicit bullet: lang/media/code_lang
SearchFilters validation is out of scope for this harness (runner uses
SearchFilters::default(), runner.rs:151). §4.1 "code 검색" row no longer
claims code_lang filter coverage.
MINOR-1: §4.3 step 3 now names kebab inspect doc <id> as the primary
chunk-selection path (breaks chunk-level curation loop); search hits
demoted to "보조 확인용".
MINOR-2: §4.1 golden category table gains two new rows — 한국어 N-gram
fallback query (복합어/신조어 coverage) and 영어 whole-token exact query
(separates substring artefacts).
MINOR-3: §4.1 YAML header note added: record corpus_revision in golden
file so stale-bail root cause is immediately traceable.
NIT: §9 References line numbers corrected (runner.rs:31, metrics.rs:116/144);
runner.rs:151 SearchFilters::default() reference added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cmd::Eval now loads Config via cli.config (same pattern as all other
subcommands) before dispatching to the inner match. Each arm now calls
the *_with_config variant:
run_eval(&opts) → run_eval_with_config(&cfg, &opts)
compute_aggregate(run_id) → compute_aggregate_with_config(&cfg, run_id)
store_aggregate(run_id, ..) → store_aggregate_with_config(&cfg, run_id, ..)
Compare already called compare_runs_with_config but sourced cfg from
Config::load(None) — that redundant load is removed; cfg comes from
the shared binding above.
Fixes the same facade-rule regression pattern as P3-5 / P4-3: previously
`kebab --config /build/dogfood/config.toml eval run` silently evaluated
the XDG-default (empty) KB instead of the dogfood KB.
Also fixes runner.rs test that hardcoded rag-v2 after commit 5719969
bumped the default prompt_template_version to rag-v3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>