From b1d50473990e55e3e14e0a58df826dffcf05c898 Mon Sep 17 00:00:00 2001 From: altair823 Date: Tue, 19 May 2026 23:24:20 +0000 Subject: [PATCH] =?UTF-8?q?fix(p10-1a-2):=20PR=20review=20round=201=20?= =?UTF-8?q?=E2=80=94=20doc=20inconsistencies=20+=20observable=20backfill?= =?UTF-8?q?=20error=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #140 회차 1 actionable 7건 반영: - docs/SMOKE.md: parser_version "code-rust-ast-v1" → "code-rust-v1" (chunker_version 과 혼동); jq path .citation.code_lang → .citation.lang (wire 의 code_lang 은 SearchHit top-level) - docs/ARCHITECTURE.md: Mermaid pcode→ptypes 잘못된 edge → pcode→core 로 정정 (kebab-parse-code Cargo.toml 실제 dep 와 일치); 디렉토리 트리에서 code-rust-ast-v1 chunker 표기 위치 kebab-parse-code → kebab-chunk 로 정정 - crates/kebab-app/src/app.rs: backfill_repo 의 .ok().flatten() 실패 silent swallow → tracing::warn 로 관측 가능, 비-abort 의도 보존 - crates/kebab-parse-code/src/rust.rs: impl_item arm 의 "function_item 만 unit 생성" 1A scope 한정 주석을 외부에서도 보이도록 arm 상단에 한 줄 추가 (내부 주석은 유지) verify: kebab-parse-code 7/7 / kebab-app --lib 51/51 / code_ingest_smoke 3/3 green; touched-crate clippy clean (재부팅 전 검증). Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/kebab-app/src/app.rs | 21 ++++++++++++++++----- crates/kebab-parse-code/src/rust.rs | 4 ++++ docs/ARCHITECTURE.md | 4 ++-- docs/SMOKE.md | 8 ++++---- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/crates/kebab-app/src/app.rs b/crates/kebab-app/src/app.rs index ff075f5..dab36b2 100644 --- a/crates/kebab-app/src/app.rs +++ b/crates/kebab-app/src/app.rs @@ -822,11 +822,22 @@ impl App { let repo_val = cache .entry(hit.doc_id.clone()) .or_insert_with(|| { - self.sqlite - .get_document(&hit.doc_id) - .ok() - .flatten() - .and_then(|doc| doc.metadata.repo) + // Deliberately non-aborting: a failed store lookup for + // one hit must not abort the whole search response. Log + // the error so it's observable rather than silently + // dropped (review #140 round 1). + match self.sqlite.get_document(&hit.doc_id) { + Ok(opt) => opt.and_then(|doc| doc.metadata.repo), + Err(e) => { + tracing::warn!( + target: "kebab-app", + doc_id = %hit.doc_id, + error = %e, + "backfill_repo: get_document failed; leaving hit.repo = None" + ); + None + } + } }); if let Some(r) = repo_val { hit.repo = Some(r.clone()); diff --git a/crates/kebab-parse-code/src/rust.rs b/crates/kebab-parse-code/src/rust.rs index 6ca75b2..f26b208 100644 --- a/crates/kebab-parse-code/src/rust.rs +++ b/crates/kebab-parse-code/src/rust.rs @@ -249,6 +249,10 @@ fn build_blocks( units.push((format!("{prefix}{name}!"), s, e, true)); } } + // `impl` blocks: emit one unit per inner `function_item`. + // Associated consts / types / non-fn members do not become + // their own units in 1A (plan §1A scope; HOTFIXES will log + // if a future need arises). See inner comment below. "impl_item" => { glue.retain(|(_, gs, _)| *gs < s); flush_glue(glue, units, &prefix); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f507776..d5952a7 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -98,7 +98,7 @@ flowchart TB ppdf --> ptypes pimg --> ptypes paud --> ptypes - pcode --> ptypes + pcode --> core norm --> ptypes embedlocal --> embed llmlocal --> llm @@ -172,7 +172,7 @@ kebab/ │ ├── kebab-eval/ # golden query runner + metrics (P5-1, P5-2) │ ├── kebab-parse-image/ # ImageExtractor + Ollama OCR + caption (P6) │ ├── kebab-parse-pdf/ # lopdf per-page text extractor (P7-1) -│ ├── kebab-parse-code/ # tree-sitter Rust AST extractor + code-rust-ast-v1 chunker (P10-1A-2) +│ ├── kebab-parse-code/ # tree-sitter Rust AST extractor (P10-1A-2); chunker lives in kebab-chunk │ ├── kebab-app/ # facade (P0 시그니처 + P3-5/P6-4/P7-3 본체) │ ├── kebab-tui/ # Ratatui shell + Library 패널 (P9-1) │ ├── kebab-mcp/ # stdio MCP server — tools: schema, doctor, search, ask (P9-FB-30) diff --git a/docs/SMOKE.md b/docs/SMOKE.md index 6ed5cc5..d44e214 100644 --- a/docs/SMOKE.md +++ b/docs/SMOKE.md @@ -313,11 +313,11 @@ cp -r crates/kebab-parse-code /tmp/kebab-smoke/workspace/kebab-parse-code # 2) ingest — .rs 가 code-rust-ast-v1 로 처리됨 KB ingest -# 3) 결과 검증 — IngestReport.items 에 .rs 자산이 "new" 로 분류, parser_version = "code-rust-ast-v1" +# 3) 결과 검증 — IngestReport.items 에 .rs 자산이 "new" 로 분류, parser_version = "code-rust-v1" (chunker_version = "code-rust-ast-v1") KB --json ingest | jq '[.items[] | select(.doc_path | endswith(".rs"))]' -# 4) 코드 검색 — code_lang 필터 -KB search --mode hybrid "RustAstExtractor" --code-lang rust --json | jq '{hits: [.hits[] | {symbol: .citation.symbol, code_lang: .citation.code_lang, repo: .repo}]}' +# 4) 코드 검색 — code_lang 필터 (wire: lang 은 citation.lang, code_lang 은 SearchHit top-level) +KB search --mode hybrid "RustAstExtractor" --code-lang rust --json | jq '{hits: [.hits[] | {symbol: .citation.symbol, code_lang: .citation.lang, repo: .repo}]}' # 5) citation 확인 — kind="code", symbol 이 함수명 / 타입명, line range 가 포함 KB search --mode lexical "pub fn extract" --code-lang rust --json | jq '.hits[0].citation' @@ -369,7 +369,7 @@ rm -rf /tmp/kebab-smoke # 통째로 정리 - (P6-4) `image.ocr.enabled = true` + `image.caption.enabled = true` 인 워크스페이스에 PNG 가 N장 있으면 ingest 시간 ≈ markdown_time + N × (OCR + Caption latency). `gemma4:e4b` + 192.168.0.47 로 자산당 ~5-10초. 다수의 책 페이지를 이미지로 넣지 말 것 — 책은 P7 PDF 라인 사용 권장. - (P7-3) `config.chunking.chunker_version` 는 markdown 만 represent — PDF 자산은 `pdf-page-v1` 하드코딩. `config.toml` 의 `chunker_version = "md-heading-v1"` 을 봐도 PDF 는 영향 안 받음. HOTFIXES `2026-05-02 P7-3` entry 참조 (P+ chunker registry task 까지 유지). - (P7-3) 한 PDF 가 N 페이지면 `kebab ingest` 가 N 개 (또는 그 이상의, 페이지 길면 multi-chunk) 의 chunk 를 한 transaction 안에서 commit. 500 페이지 책 → 500+ chunk 한 번에 → embedding throughput 가 bottleneck. 임베딩 활성 워크스페이스에서 큰 PDF 를 처음 ingest 하면 분-단위 시간 + WAL 크기 증가 가능 — P+ 스케일 hardening task 까지 정상 동작이지만 비용은 측정 가능. -- (P10-1A-2) `.rs` 파일을 워크스페이스에 두면 `kebab ingest` 결과에 `new` 카운터에 포함. `kebab search --mode hybrid "<함수명>" --code-lang rust --json` 가 `citation.kind = "code"`, `citation.code_lang = "rust"`, `citation.symbol` (함수/타입 이름), `citation.line_start` / `citation.line_end` 를 반환하면 wiring 정상. `kebab schema --json | jq .stats.code_lang_breakdown` 에 `"rust": N` 이 나오면 chunk 가 색인됨. +- (P10-1A-2) `.rs` 파일을 워크스페이스에 두면 `kebab ingest` 결과에 `new` 카운터에 포함. `kebab search --mode hybrid "<함수명>" --code-lang rust --json` 가 `citation.kind = "code"`, `citation.lang = "rust"` (SearchHit top-level `code_lang` 도 동일), `citation.symbol` (함수/타입 이름), `citation.line_start` / `citation.line_end` 를 반환하면 wiring 정상. `kebab schema --json | jq .stats.code_lang_breakdown` 에 `"rust": N` 이 나오면 chunk 가 색인됨. - (P7-3 + follow-up) 동일 path 에 byte 가 다른 PDF 를 두 번째 ingest 하면 `purge_vector_orphans_for_workspace_path` 가 옛 chunk_id 를 LanceDB 에서 먼저 삭제, 이어서 `purge_orphan_at_workspace_path` 가 옛 doc / chunks / embedding_records 를 SQLite 에서 sweep. 새 byte 가 새 `doc_id` 로 색인됨. `IngestReport` 에 그 자산만 `new+=1` (다른 자산은 `updated`). 두 store 모두 정합 — 옛 본문 검색 시 옛 chunks 가 더 이상 surface 되지 않음. ### Embedding upgrade (fb-39b)