chore(search): PR #219 회차 1 리뷰 반영 — 잔존 dead-cache 주석/help text 정리

리뷰어 지적 6건 + 전체-트리 grep 으로 추가 발견한 동일 부류 4건:
- search --trace help text(CLI main.rs + MCP search tool) "Bypasses cache"
  → "always a fresh retriever run" (없는 캐시 광고 제거)
- corpus_revision 의 실제 소비자는 incremental ingest 가 아니라 cursor
  pagination(stale_cursor) 임을 반영 — HANDOFF 노트 사실 정정 + ingest.rs
  bump 주석/warn 로그 + corpus_revision/search_lexical 테스트 주석 재서술
  (검증: cursor.rs + app.rs:327/333/498 가 유일 소비자, ingest 는 bump 만)
- bulk.rs "LRU cache amortize" → embedder cold-start 만 amortize
- app.rs lexical_index_version "search cache 무효화" 제거
- app-facade README 의 search cache bullet 을 "(제거됨 — 이력)" 표시

잔여 dead-cache 개념 참조 0건(active tree), clippy -D warnings 클린.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
This commit is contained in:
2026-06-26 17:25:03 +00:00
parent db9090c87b
commit 8dfeb007e0
8 changed files with 17 additions and 16 deletions

View File

@@ -774,7 +774,7 @@ impl App {
/// V009 (2026-05-28): FTS5 tokenizer 가 trigram → unicode61 + 한국어 /// V009 (2026-05-28): FTS5 tokenizer 가 trigram → unicode61 + 한국어
/// 형태소 분해 column 로 갱신됨. `fts5-v009-korean-morphological` /// 형태소 분해 column 로 갱신됨. `fts5-v009-korean-morphological`
/// suffix 가 V007 baseline 과 구별되어 eval runner 의 config /// suffix 가 V007 baseline 과 구별되어 eval runner 의 config
/// snapshot 및 search cache 무효화에 picks up 된다. /// snapshot 에 picks up 된다.
fn lexical_index_version(config: &kebab_config::Config) -> IndexVersion { fn lexical_index_version(config: &kebab_config::Config) -> IndexVersion {
IndexVersion(format!( IndexVersion(format!(
"lex:{}:fts5-v009-korean-morphological", "lex:{}:fts5-v009-korean-morphological",

View File

@@ -1,5 +1,5 @@
//! p9-fb-42: bulk multi-query facade. Sequential for-loop reusing //! p9-fb-42: bulk multi-query facade. Sequential for-loop reusing
//! one App instance so embedder cold-start + LRU cache amortize //! one App instance so the embedder cold-start amortizes
//! across the N queries. //! across the N queries.
use anyhow::Context; use anyhow::Context;

View File

@@ -604,10 +604,10 @@ pub fn ingest_with_config(
crate::ingest_progress::emit(progress, terminal_event); crate::ingest_progress::emit(progress, terminal_event);
// p9-fb-19: bump the persistent corpus_revision counter when a // p9-fb-19: bump the persistent corpus_revision counter when a
// commit landed (any new / updated / purged). This invalidates every // commit landed (any new / updated / purged). This invalidates any
// entry in any in-process LRU search cache (in this process or // outstanding search pagination cursors (stale_cursor) on the next
// a sibling) on the next lookup. No-op when nothing changed // page request. No-op when nothing changed (skipped-only run) —
// (skipped-only run) — the cache stays valid. // outstanding cursors stay valid.
if new_count > 0 || updated_count > 0 || purged_deleted_files > 0 { if new_count > 0 || updated_count > 0 || purged_deleted_files > 0 {
match app.sqlite.bump_corpus_revision() { match app.sqlite.bump_corpus_revision() {
Ok(rev) => tracing::debug!( Ok(rev) => tracing::debug!(
@@ -618,7 +618,7 @@ pub fn ingest_with_config(
Err(e) => tracing::warn!( Err(e) => tracing::warn!(
target: "kebab-app", target: "kebab-app",
error = %e, error = %e,
"bump_corpus_revision failed; cache may serve stale results until process restart" "bump_corpus_revision failed; outstanding search cursors may not be invalidated until the next successful ingest"
), ),
} }
} }

View File

@@ -90,7 +90,7 @@ fn first_ingest_bumps_corpus_revision() {
let store_before = kebab_store_sqlite::SqliteStore::open(&env.config.storage).unwrap(); let store_before = kebab_store_sqlite::SqliteStore::open(&env.config.storage).unwrap();
store_before.run_migrations().unwrap(); store_before.run_migrations().unwrap();
// V004 seeds 0; V009 + V010 + V011 migrations each bump by 1 to // V004 seeds 0; V009 + V010 + V011 migrations each bump by 1 to
// invalidate stale LRU caches (spec §5.2). Baseline before ingest = 3. // invalidate outstanding pagination cursors (spec §5.2). Baseline before ingest = 3.
// (V012 derivation_cache + V013 drop-chunk-aliases are structural/additive // (V012 derivation_cache + V013 drop-chunk-aliases are structural/additive
// — neither bumps corpus_revision.) // — neither bumps corpus_revision.)
let baseline = store_before.corpus_revision(); let baseline = store_before.corpus_revision();

View File

@@ -206,8 +206,8 @@ enum Cmd {
source: Vec<String>, source: Vec<String>,
/// p9-fb-37: emit pre-fusion lexical / vector / RRF candidate /// p9-fb-37: emit pre-fusion lexical / vector / RRF candidate
/// lists + per-stage timing in the response. Bypasses cache /// lists + per-stage timing in the response (debug intent —
/// (debug intent — fresh run guaranteed). Requires embeddings /// always a fresh retriever run). Requires embeddings
/// when `--mode hybrid` or `--mode vector`; lexical mode runs /// when `--mode hybrid` or `--mode vector`; lexical mode runs
/// without embeddings via a no-op vector stub. /// without embeddings via a no-op vector stub.
#[arg(long)] #[arg(long)]

View File

@@ -49,7 +49,7 @@ pub struct SearchInput {
pub doc_id: Option<String>, pub doc_id: Option<String>,
/// p9-fb-37: when true, include a `trace` field on the response /// p9-fb-37: when true, include a `trace` field on the response
/// with pre-fusion lexical/vector candidate lists + per-stage timing. /// with pre-fusion lexical/vector candidate lists + per-stage timing.
/// Bypasses cache (debug intent — fresh run guaranteed). Default false. /// Debug intent — always a fresh retriever run. Default false.
pub trace: Option<bool>, pub trace: Option<bool>,
} }

View File

@@ -1,7 +1,7 @@
//! p9-fb-19: `corpus_revision` kv counter — exposed on `SqliteStore` //! p9-fb-19: `corpus_revision` kv counter — exposed on `SqliteStore`
//! so `kebab-app::ingest` can bump after a successful commit and //! so `kebab-app::ingest` can bump after a successful commit and
//! `App::search`'s LRU cache key can snapshot the current value for //! search pagination cursors can snapshot the current value to detect
//! invalidation. //! staleness (`stale_cursor`).
use kebab_config::Config; use kebab_config::Config;
use kebab_store_sqlite::SqliteStore; use kebab_store_sqlite::SqliteStore;
@@ -21,8 +21,9 @@ fn open_store(tmp: &TempDir) -> SqliteStore {
} }
/// Fresh store baseline: V004 seeds `corpus_revision = 0`, then V009, /// Fresh store baseline: V004 seeds `corpus_revision = 0`, then V009,
/// V010, and V011 migrations bump it by one each to invalidate any stale /// V010, and V011 migrations bump it by one each to invalidate any
/// LRU cache — so a fresh store after `run_migrations()` reads back as `3`. /// outstanding pagination cursor — so a fresh store after
/// `run_migrations()` reads back as `3`.
/// (V012 derivation_cache + V013 drop-chunk-aliases are structural/additive /// (V012 derivation_cache + V013 drop-chunk-aliases are structural/additive
/// and do NOT bump corpus_revision.) /// and do NOT bump corpus_revision.)
#[test] #[test]

View File

@@ -177,6 +177,6 @@ flowchart LR
- app skeleton + ingest wiring: [`tasks/p3/p3-5-app-wiring.md`](../../../tasks/p3/p3-5-app-wiring.md), [`tasks/p6/p6-4-image-ingest-wiring.md`](../../../tasks/p6/p6-4-image-ingest-wiring.md), [`tasks/p7/p7-3-pdf-ingest-wiring.md`](../../../tasks/p7/p7-3-pdf-ingest-wiring.md) - app skeleton + ingest wiring: [`tasks/p3/p3-5-app-wiring.md`](../../../tasks/p3/p3-5-app-wiring.md), [`tasks/p6/p6-4-image-ingest-wiring.md`](../../../tasks/p6/p6-4-image-ingest-wiring.md), [`tasks/p7/p7-3-pdf-ingest-wiring.md`](../../../tasks/p7/p7-3-pdf-ingest-wiring.md)
- reset: [`tasks/p9/p9-fb-06-data-reset-command.md`](../../../tasks/p9/p9-fb-06-data-reset-command.md) - reset: [`tasks/p9/p9-fb-06-data-reset-command.md`](../../../tasks/p9/p9-fb-06-data-reset-command.md)
- ingest progress / cancel: [`tasks/p9/p9-fb-03-tui-ingest-background.md`](../../../tasks/p9/p9-fb-03-tui-ingest-background.md), [`tasks/p9/p9-fb-04-ingest-cancellation.md`](../../../tasks/p9/p9-fb-04-ingest-cancellation.md) - ingest progress / cancel: [`tasks/p9/p9-fb-03-tui-ingest-background.md`](../../../tasks/p9/p9-fb-03-tui-ingest-background.md), [`tasks/p9/p9-fb-04-ingest-cancellation.md`](../../../tasks/p9/p9-fb-04-ingest-cancellation.md)
- search cache: [`tasks/p9/p9-fb-19-search-cache.md`](../../../tasks/p9/p9-fb-19-search-cache.md) - search cache (제거됨 — 이력): [`tasks/p9/p9-fb-19-search-cache.md`](../../../tasks/p9/p9-fb-19-search-cache.md)
- chat session CLI: [`tasks/p9/p9-fb-18-cli-ask-session-repl.md`](../../../tasks/p9/p9-fb-18-cli-ask-session-repl.md) - chat session CLI: [`tasks/p9/p9-fb-18-cli-ask-session-repl.md`](../../../tasks/p9/p9-fb-18-cli-ask-session-repl.md)
- HOTFIXES (P3-5/P4-3 `--config` 누락 + `*_with_config` 패턴, P7-3 storage UNIQUE bug, p9-fb-* 도그푸딩 후속): [`tasks/HOTFIXES.md`](../../../tasks/HOTFIXES.md) - HOTFIXES (P3-5/P4-3 `--config` 누락 + `*_with_config` 패턴, P7-3 storage UNIQUE bug, p9-fb-* 도그푸딩 후속): [`tasks/HOTFIXES.md`](../../../tasks/HOTFIXES.md)