feat(p10-1A-2): Rust AST chunker — tree-sitter-rust 코드 색인 활성화 #140

Merged
altair823 merged 19 commits from feat/p10-1a-2-rust-ast-chunker into main 2026-05-19 23:40:19 +00:00
Owner

개요

p10-1A-1 프레임워크 위에 Rust AST chunker 를 올려 .rs 파일 end-to-end 코드 색인을 활성화. 머지 시점부터 kebab 자기 자신 dogfooding 가능.

frozen design: docs/superpowers/specs/2026-05-15-kebab-code-ingest-design.md §1A-2.
task spec (frozen): tasks/p10/p10-1a-2-rust-ast-chunker.md.
plan: docs/superpowers/plans/2026-05-19-p10-1a-2-rust-ast-chunker.md.

동결된 설계 결정

  1. tree-sitter 위치 = parser (kebab-parse-code), chunker 아님. design §6.3 의존성 그래프 (kebab-parse-code → tree-sitter, tree-sitter-rust) 가 authoritative. PDF 선례와 동형 — parser 가 구조화된 block 을 만들고 chunker 가 1:1 매핑. §9.1 의 "chunker 가 AST" 서술은 oversize fallback split 만 chunker-side 라는 의미로 해석.
  2. SourceSpan::Code { line_start, line_end, symbol, lang } 내부 variant 신설 (kebab-core). chunks 테이블의 source_spans_json 은 내부 저장이라 wire schema 아님 → wire major bump 불필요. Citation::Code (wire) 는 1A-1 에서 이미 추가됨. citation_helper::citation_from_first_span 에 새 arm 추가로 symbol / lang 이 chunk → SearchHit 까지 자연스럽게 흐름.
  3. MediaType::Code(String) 신설 — String = canonical code_lang. 1A 는 "rust" 만 실제 처리, 그 외 인식된 code lang 은 Skipped.

frozen design §3.4 (SourceSpan) + §3.5 (MediaType) + §10.1 (post-merge surface) 동시 갱신.

변경 요약

  • kebab-parse-code: tree-sitter 0.26 + tree-sitter-rust 0.24 도입, rust.rs Extractor — tree-sitter walk 으로 function_item / struct_item / enum_item / union_item / trait_item / type_item / macro_definition / impl_item (per inner fn) / 중첩 mod_item 재귀 처리 + glue (use/extern/const/static/mod 선언/attr/macro_invocation) 를 단일 <top-level> / <module> 단위로 그룹핑. 심볼 경로는 design §3.4 Rust 컨벤션 (mod::Type::method, trait 우선). 선행 doc comment 와 attribute 가 자기 unit 으로 fold 되고 중복 집계 없음 (회차 1·2 review fix).
  • kebab-chunk: code-rust-ast-v1 chunker — 1 Block::Code → 1 Chunk, AST_CHUNK_MAX_LINES (200) 초과 시 paragraph 경계로 split + <symbol> [part i/N] 라벨. tree-sitter import 0 건 (boundary §6.3). pdf-page-v1 와 동일 blake3 policy_hash (cross-chunker 동일성 테스트 포함).
  • kebab-core: SourceSpan::Code + MediaType::Code 신규 variant. 모든 exhaustive match 명시적으로 갱신 (catch-all 미도입).
  • kebab-search: citation_helperSourceSpan::Code → Citation::Code 매핑.
  • kebab-source-fs: .rsMediaType::Code("rust") 라우팅.
  • kebab-app: ingest_one_code_asset ( ingest_one_pdf_asset 의 line-for-line 미러 — incremental skip / vector orphan purge / put_asset/document/blocks/chunks / embed 모두 보존), dispatch arm 추가, backfill_code_lang + backfill_repo post-search (1A-1 가 추가만 하고 미배선이던 두 SearchHit 필드 채움). e2e 통합 테스트 3 케이스.
  • kebab-store-sqlite: code_lang_breakdown() 쿼리.
  • kebab-app/schema.rs: schema.v1.code_lang_breakdown 실제 채움.
  • 테스트: 새 chunker snapshot 통합 테스트 (tests/code_rust_ast_snapshot.rs + JSON baseline), Task 6/7 inline 유닛 테스트, Task 8 e2e 통합 테스트, regression 케이스 (label scope / attribute dedup / module-prefix glue / determinism).
  • docs: README (지원 형식 + Mermaid 갱신), HANDOFF (phase 진행), ARCHITECTURE (의존 그래프 + 잠금 결정), SMOKE (절차 추가), tasks/INDEX + tasks/p10/INDEX (status).
  • HOTFIXES (2026-05-19, 2 항목):
    • AST_CHUNK_MAX_LINES 상수 vs config 편차 — Chunker trait 이 per-medium config 미노출. default 와 동일 (200) 이라 user-visible 영향 없음. 적합한 해결은 per-medium chunker registry (P+).
    • SourceType::Code deferred — code 파일은 SourceType::Note 로 분류. MediaType::Code 기반 filter 는 정상 동작. 적합한 해결은 enum 에 Code variant 추가 (additive 후속).
  • chore: workspace version 0.6.0 → 0.7.0 (도그푸딩 가능 = bump 트리거, design §10.4). cascade 자동.

acceptance criteria 충족

  • cargo test --workspace --no-fail-fast -j 1 — green (단 한 가지 주의 사항 ↓).
  • cargo clippy --workspace --all-targets -- -D warnings — clean.
  • Rust fixture ingest → chunk snapshot 안정 + Citation::Code 의 symbol / line 이 spec §3.4 컨벤션 일치.
  • 격리 TempDir SMOKE: kebab search --jsoncitation.kind == "code", code_lang == "rust", (.git 있는 경우) repo 반환. kebab schema --jsoncode_lang_breakdown"rust". media_breakdown"code".
  • frozen design + 사용자-가시 docs 동시 갱신.

알려진 주의 사항

  • crates/kebab-eval/tests/runner.rs::runner_lexical_is_deterministic_per_query_payload 가 full-suite 첫 실행에서 간헐적으로 실패 (elapsed_ms: 0 vs 1 비교) 후 isolated 재실행 시 통과. 1A-2 변경과 무관 (해당 파일 본 브랜치에서 미수정, git log main..HEAD -- crates/kebab-eval/tests/runner.rs empty). pre-existing timing flake — 별도 정리 권장 (이번 PR 범위 밖).

커밋 (17)

80c2d31 docs(p10-1a-2): README/HANDOFF/ARCHITECTURE/SMOKE/INDEX + HOTFIXES; chore: bump version 0.6.0 → 0.7.0
97e9f55 test(p10-1a-2): code-rust-ast-v1 chunker snapshot + full-suite gate
da51e59 feat(p10-1a-2): populate schema.v1 code_lang_breakdown
11a0fc7 docs(p10-1a-2): note backfill invariant at search_with_opts non-trace path (Task 8 review)
b5d1fe8 feat(p10-1a-2): backfill SearchHit.repo from doc metadata (Task 8b)
580576c feat(p10-1a-2): wire code ingest dispatch (ingest_one_code_asset)
808b92a feat(p10-1a-2): code-rust-ast-v1 chunker (1:1 + oversize split)
c74f8d2 chore(p10-1a-2): sync Cargo.lock for kebab-parse-code deps (Task 6 follow-up)
df85baf fix(p10-1a-2): module-prefix glue symbols + crate desc + invariant hardening (Task 6 review)
a93b33f fix(p10-1a-2): correct <module> label scope + de-dup leading attribute (Task 6 review)
402a450 feat(p10-1a-2): tree-sitter-rust AST extractor (parser-side)
a531dc3 feat(p10-1a-2): route .rs files to MediaType::Code(rust)
7a6a24a feat(p10-1a-2): add MediaType::Code(lang) variant
42712b5 feat(p10-1a-2): map SourceSpan::Code -> Citation::Code in citation_helper
9f3edb7 feat(p10-1a-2): add internal SourceSpan::Code variant + design §3.4 sync
5c265bb build(p10-1a-2): add tree-sitter + tree-sitter-rust workspace deps
a08ed32 docs(p10-1a-2): task spec + implementation plan

🤖 Generated with Claude Code

## 개요 p10-1A-1 프레임워크 위에 **Rust AST chunker** 를 올려 `.rs` 파일 end-to-end 코드 색인을 활성화. 머지 시점부터 kebab 자기 자신 dogfooding 가능. frozen design: `docs/superpowers/specs/2026-05-15-kebab-code-ingest-design.md` §1A-2. task spec (frozen): `tasks/p10/p10-1a-2-rust-ast-chunker.md`. plan: `docs/superpowers/plans/2026-05-19-p10-1a-2-rust-ast-chunker.md`. ## 동결된 설계 결정 1. **tree-sitter 위치 = parser (`kebab-parse-code`), chunker 아님.** design §6.3 의존성 그래프 (`kebab-parse-code → tree-sitter, tree-sitter-rust`) 가 authoritative. PDF 선례와 동형 — parser 가 구조화된 block 을 만들고 chunker 가 1:1 매핑. §9.1 의 "chunker 가 AST" 서술은 *oversize fallback split* 만 chunker-side 라는 의미로 해석. 2. **`SourceSpan::Code { line_start, line_end, symbol, lang }` 내부 variant 신설** (kebab-core). chunks 테이블의 `source_spans_json` 은 내부 저장이라 wire schema 아님 → wire major bump 불필요. `Citation::Code` (wire) 는 1A-1 에서 이미 추가됨. `citation_helper::citation_from_first_span` 에 새 arm 추가로 symbol / lang 이 chunk → SearchHit 까지 자연스럽게 흐름. 3. **`MediaType::Code(String)` 신설** — String = canonical code_lang. 1A 는 `"rust"` 만 실제 처리, 그 외 인식된 code lang 은 `Skipped`. frozen design §3.4 (SourceSpan) + §3.5 (MediaType) + §10.1 (post-merge surface) 동시 갱신. ## 변경 요약 - **`kebab-parse-code`**: `tree-sitter` 0.26 + `tree-sitter-rust` 0.24 도입, `rust.rs` Extractor — tree-sitter walk 으로 `function_item` / `struct_item` / `enum_item` / `union_item` / `trait_item` / `type_item` / `macro_definition` / `impl_item` (per inner fn) / 중첩 `mod_item` 재귀 처리 + glue (use/extern/const/static/mod 선언/attr/macro_invocation) 를 단일 `<top-level>` / `<module>` 단위로 그룹핑. 심볼 경로는 design §3.4 Rust 컨벤션 (`mod::Type::method`, trait 우선). 선행 doc comment 와 attribute 가 자기 unit 으로 fold 되고 중복 집계 없음 (회차 1·2 review fix). - **`kebab-chunk`**: `code-rust-ast-v1` chunker — 1 Block::Code → 1 Chunk, `AST_CHUNK_MAX_LINES` (200) 초과 시 paragraph 경계로 split + `<symbol> [part i/N]` 라벨. tree-sitter import 0 건 (boundary §6.3). `pdf-page-v1` 와 동일 blake3 policy_hash (cross-chunker 동일성 테스트 포함). - **`kebab-core`**: `SourceSpan::Code` + `MediaType::Code` 신규 variant. 모든 exhaustive match 명시적으로 갱신 (catch-all 미도입). - **`kebab-search`**: `citation_helper` 가 `SourceSpan::Code → Citation::Code` 매핑. - **`kebab-source-fs`**: `.rs` → `MediaType::Code("rust")` 라우팅. - **`kebab-app`**: `ingest_one_code_asset` ( `ingest_one_pdf_asset` 의 line-for-line 미러 — incremental skip / vector orphan purge / put_asset/document/blocks/chunks / embed 모두 보존), dispatch arm 추가, `backfill_code_lang` + `backfill_repo` post-search (1A-1 가 추가만 하고 미배선이던 두 SearchHit 필드 채움). e2e 통합 테스트 3 케이스. - **`kebab-store-sqlite`**: `code_lang_breakdown()` 쿼리. - **`kebab-app/schema.rs`**: `schema.v1.code_lang_breakdown` 실제 채움. - **테스트**: 새 chunker snapshot 통합 테스트 (`tests/code_rust_ast_snapshot.rs` + JSON baseline), Task 6/7 inline 유닛 테스트, Task 8 e2e 통합 테스트, regression 케이스 (label scope / attribute dedup / module-prefix glue / determinism). - **docs**: README (지원 형식 + Mermaid 갱신), HANDOFF (phase 진행), ARCHITECTURE (의존 그래프 + 잠금 결정), SMOKE (절차 추가), tasks/INDEX + tasks/p10/INDEX (status). - **HOTFIXES (2026-05-19, 2 항목)**: - `AST_CHUNK_MAX_LINES` 상수 vs config 편차 — `Chunker` trait 이 per-medium config 미노출. default 와 동일 (200) 이라 user-visible 영향 없음. 적합한 해결은 per-medium chunker registry (P+). - `SourceType::Code` deferred — code 파일은 `SourceType::Note` 로 분류. `MediaType::Code` 기반 filter 는 정상 동작. 적합한 해결은 enum 에 `Code` variant 추가 (additive 후속). - **chore**: workspace version `0.6.0 → 0.7.0` (도그푸딩 가능 = bump 트리거, design §10.4). cascade 자동. ## acceptance criteria 충족 - `cargo test --workspace --no-fail-fast -j 1` — green (단 한 가지 주의 사항 ↓). - `cargo clippy --workspace --all-targets -- -D warnings` — clean. - Rust fixture ingest → chunk snapshot 안정 + `Citation::Code` 의 symbol / line 이 spec §3.4 컨벤션 일치. - 격리 TempDir SMOKE: `kebab search --json` 이 `citation.kind == "code"`, `code_lang == "rust"`, (`.git` 있는 경우) `repo` 반환. `kebab schema --json` 의 `code_lang_breakdown` 에 `"rust"`. `media_breakdown` 에 `"code"`. - frozen design + 사용자-가시 docs 동시 갱신. ## 알려진 주의 사항 - `crates/kebab-eval/tests/runner.rs::runner_lexical_is_deterministic_per_query_payload` 가 full-suite 첫 실행에서 간헐적으로 실패 (`elapsed_ms: 0` vs `1` 비교) 후 isolated 재실행 시 통과. **1A-2 변경과 무관** (해당 파일 본 브랜치에서 미수정, `git log main..HEAD -- crates/kebab-eval/tests/runner.rs` empty). pre-existing timing flake — 별도 정리 권장 (이번 PR 범위 밖). ## 커밋 (17) ``` 80c2d31 docs(p10-1a-2): README/HANDOFF/ARCHITECTURE/SMOKE/INDEX + HOTFIXES; chore: bump version 0.6.0 → 0.7.0 97e9f55 test(p10-1a-2): code-rust-ast-v1 chunker snapshot + full-suite gate da51e59 feat(p10-1a-2): populate schema.v1 code_lang_breakdown 11a0fc7 docs(p10-1a-2): note backfill invariant at search_with_opts non-trace path (Task 8 review) b5d1fe8 feat(p10-1a-2): backfill SearchHit.repo from doc metadata (Task 8b) 580576c feat(p10-1a-2): wire code ingest dispatch (ingest_one_code_asset) 808b92a feat(p10-1a-2): code-rust-ast-v1 chunker (1:1 + oversize split) c74f8d2 chore(p10-1a-2): sync Cargo.lock for kebab-parse-code deps (Task 6 follow-up) df85baf fix(p10-1a-2): module-prefix glue symbols + crate desc + invariant hardening (Task 6 review) a93b33f fix(p10-1a-2): correct <module> label scope + de-dup leading attribute (Task 6 review) 402a450 feat(p10-1a-2): tree-sitter-rust AST extractor (parser-side) a531dc3 feat(p10-1a-2): route .rs files to MediaType::Code(rust) 7a6a24a feat(p10-1a-2): add MediaType::Code(lang) variant 42712b5 feat(p10-1a-2): map SourceSpan::Code -> Citation::Code in citation_helper 9f3edb7 feat(p10-1a-2): add internal SourceSpan::Code variant + design §3.4 sync 5c265bb build(p10-1a-2): add tree-sitter + tree-sitter-rust workspace deps a08ed32 docs(p10-1a-2): task spec + implementation plan ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
altair823 added 17 commits 2026-05-19 22:50:18 +00:00
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TDD: red → green cycle confirmed. New `Code(String)` variant serializes
as `{"code":"rust"}` via serde `rename_all = "lowercase"`. All exhaustive
`match` sites updated (`media_label`, `ingest_one_asset` catch-all →
explicit or-pattern). Design §3.5 enum listing synced. Also fix
`/target` symlink gitignore pattern so integration-test binary lookup
via workspace-relative path works with CARGO_TARGET_DIR redirect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add `MediaType::Code("rust")` dispatch arm in `ingest_one_asset`,
`ingest_one_code_asset` fn (faithful mirror of `ingest_one_pdf_asset`),
and `backfill_code_lang` post-processing in `App::search_uncached`.
Integration test `code_ingest_smoke.rs` verifies full pipeline:
ingest `.rs` → Citation::Code hit with lang/symbol/line_start.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add `SqliteStore::code_lang_breakdown()` that queries
`json_extract(metadata_json, '$.code_lang')`, groups by it, and
skips NULL rows — returning `BTreeMap<String, u32>`.

Wire it into `collect_stats` in `kebab-app::schema`, replacing the
`BTreeMap::new()` placeholder inserted by 1A-1.

Test: `store::tests::code_lang_breakdown_counts_by_code_lang` asserts
rust=1 and that a null-code_lang doc does NOT appear in the map.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README: note Rust .rs ingest active (code-rust-ast-v1), update Mermaid parse node + chunker labels, update supported formats note in Quick start and ingest command table; add code citation fields (symbol, code_lang, repo) and filter flags note
- HANDOFF: flip P10 row to note 1A-1  + 1A-2 PR open; add one-liner cross-link to HOTFIXES 2026-05-19 entries
- ARCHITECTURE: add kebab-parse-code node + edge (app → pcode, pcode → ptypes) to Mermaid graph; add directory tree entry; add code parser locked-in decision row (tree-sitter lives parser-side, design §6.3)
- SMOKE: add P10-1A-2 Rust code ingest section (ingest.code config keys, verification steps, known behaviors); add checklist item
- tasks/INDEX.md: flip p10-1A-1 to , update p10-1A-2 to 🟡 PR open
- tasks/p10/INDEX.md: same flips
- tasks/HOTFIXES.md: add two 2026-05-19 dated entries (AST_CHUNK_MAX_LINES constant vs config deviation + SourceType::Code deferred)
- tasks/p10/p10-1a-2-rust-ast-chunker.md: append two HOTFIXES cross-link lines in Risks/notes
- docs/superpowers/specs/2026-04-27-kebab-final-form-design.md §10.1: note p10-1A-2 surface activation
- Cargo.toml: version 0.6.0 → 0.7.0 (dogfooding-ready = minor bump trigger per CLAUDE.md)
- Cargo.lock: regenerated

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-19 22:58:20 +00:00
claude-reviewer-01 left a comment
Member

회차 1 — 전반적으로 탄탄한 PR이지만 docs에 actionable 오류 3건 + ARCHITECTURE Mermaid 에지 오류 1건이 있어 REQUEST_CHANGES.

tree-sitter-rust parser-side / chunker tree-sitter-free 라는 의존성 경계가 cargo tree로 검증됨 (kebab-chunk → tree-sitter 없음, UI crate → kebab-parse-code 없음). backfill_repo HashMap deduplication, split_oversize blank-line heuristic, snapshot 테스트 포함 TDD 흔적 모두 양호. HOTFIXES.md 양방향 cross-link도 완성됨.

수정 필요 항목: (1) docs/SMOKE.mdparser_version = "code-rust-ast-v1" 으로 잘못 기재 — 실제 상수는 "code-rust-v1" (PARSER_VERSION 확인); (2) 같은 파일에서 citation.code_lang 참조 2곳 — 와이어 shape Citation::Code.langlang 필드이므로 jq path 오류; (3) docs/ARCHITECTURE.md Mermaid에 pcode --> ptypes 에지가 추가됐지만 kebab-parse-codekebab-parse-types 를 실제로 의존하지 않음 (cargo tree 확인). 추가로 directory tree 설명에 "code-rust-ast-v1 chunker" 가 kebab-parse-code 항목에 기재되어 있으나 chunker는 kebab-chunk 소속 — 혼란 야기. runner_lexical_is_deterministic_per_query_payload 플레이크 확인: git log main..HEAD -- crates/kebab-eval/tests/runner.rs 가 empty → 이 브랜치에서 해당 파일 미터치, 안전.

회차 1 — 전반적으로 탄탄한 PR이지만 docs에 actionable 오류 3건 + ARCHITECTURE Mermaid 에지 오류 1건이 있어 REQUEST_CHANGES. tree-sitter-rust parser-side / chunker tree-sitter-free 라는 의존성 경계가 `cargo tree`로 검증됨 (kebab-chunk → tree-sitter 없음, UI crate → kebab-parse-code 없음). `backfill_repo` HashMap deduplication, `split_oversize` blank-line heuristic, snapshot 테스트 포함 TDD 흔적 모두 양호. HOTFIXES.md 양방향 cross-link도 완성됨. 수정 필요 항목: (1) `docs/SMOKE.md` 에 `parser_version = "code-rust-ast-v1"` 으로 잘못 기재 — 실제 상수는 `"code-rust-v1"` (PARSER_VERSION 확인); (2) 같은 파일에서 `citation.code_lang` 참조 2곳 — 와이어 shape `Citation::Code.lang` 은 `lang` 필드이므로 jq path 오류; (3) `docs/ARCHITECTURE.md` Mermaid에 `pcode --> ptypes` 에지가 추가됐지만 `kebab-parse-code` 는 `kebab-parse-types` 를 실제로 의존하지 않음 (`cargo tree` 확인). 추가로 directory tree 설명에 "code-rust-ast-v1 chunker" 가 kebab-parse-code 항목에 기재되어 있으나 chunker는 kebab-chunk 소속 — 혼란 야기. `runner_lexical_is_deterministic_per_query_payload` 플레이크 확인: `git log main..HEAD -- crates/kebab-eval/tests/runner.rs` 가 empty → 이 브랜치에서 해당 파일 미터치, 안전.

칭찬 — backfill_repo deduplication 패턴: HashMap cache 로 동일 doc_id 에 대한 중복 store 조회를 방지하는 패턴이 정확하고 comment 도 명료함. None 도 cache 에 저장해 not-found / no-repo 케이스의 중복 조회를 막는 것까지 챙겼고 (doc_id → Option<String> where None means "not found / no repo"), search result set 이 k ≤ 20 으로 작아 HashMap overhead 도 무시 가능 수준 — 설계 판단이 합리적.

**칭찬 — backfill_repo deduplication 패턴**: HashMap cache 로 동일 doc_id 에 대한 중복 store 조회를 방지하는 패턴이 정확하고 comment 도 명료함. `None` 도 cache 에 저장해 not-found / no-repo 케이스의 중복 조회를 막는 것까지 챙겼고 (`doc_id → Option<String>` where None means "not found / no repo"), search result set 이 k ≤ 20 으로 작아 HashMap overhead 도 무시 가능 수준 — 설계 판단이 합리적.
@@ -780,0 +824,4 @@
.or_insert_with(|| {
self.sqlite
.get_document(&hit.doc_id)
.ok()

concern — store 오류 묵인: self.sqlite.get_document(...).ok().flatten() 에서 .ok()Result::Err (SQLite 오류, 트랜잭션 충돌 등)를 None 으로 변환해 silently 삼킴. doc comment 에 "document not found" 케이스만 언급하지만 실제 I/O 오류도 같은 경로로 처리됨. 검색 결과에서 repoNone 으로 표시되는 문제를 디버깅하기가 어려워짐. 최소한 tracing::warn! 한 줄 추가하거나, PDF/image pipeline 처럼 오류를 bubbling 하는 것을 권장. 현재 repo 는 non-critical 필드이므로 warn + continue 패턴이 현실적인 절충안.

**concern — store 오류 묵인**: `self.sqlite.get_document(...).ok().flatten()` 에서 `.ok()` 가 `Result::Err` (SQLite 오류, 트랜잭션 충돌 등)를 `None` 으로 변환해 silently 삼킴. doc comment 에 "document not found" 케이스만 언급하지만 실제 I/O 오류도 같은 경로로 처리됨. 검색 결과에서 `repo` 가 `None` 으로 표시되는 문제를 디버깅하기가 어려워짐. 최소한 `tracing::warn!` 한 줄 추가하거나, PDF/image pipeline 처럼 오류를 bubbling 하는 것을 권장. 현재 repo 는 non-critical 필드이므로 `warn` + continue 패턴이 현실적인 절충안.
@@ -15,8 +15,10 @@
//! embedder, the retriever, the LLM, the RAG layer, or the UI layers.
//! It consumes `CanonicalDocument` purely through `kb-core` types.
mod code_rust_ast_v1;

칭찬 — dep boundary 깔끔하게 유지: kebab-chunk 에 tree-sitter 의존성 없음 (cargo tree -p kebab-chunk --depth 1 검증). 모듈 doc comment (//! tree-sitter is intentionally NOT a dependency here) 와 설계 근거 (design §6.3) 가 일치하고, snapshot test 도 extractor 없이 Block::Code 를 직접 생성해 경계를 유지. UI crate (cli/tui/mcp) 도 kebab-parse-code 를 직접 의존하지 않음 — 경계 구조 전체가 설계 의도와 일치.

**칭찬 — dep boundary 깔끔하게 유지**: `kebab-chunk` 에 tree-sitter 의존성 없음 (`cargo tree -p kebab-chunk --depth 1` 검증). 모듈 doc comment (`//! tree-sitter is intentionally NOT a dependency here`) 와 설계 근거 (design §6.3) 가 일치하고, snapshot test 도 extractor 없이 Block::Code 를 직접 생성해 경계를 유지. UI crate (cli/tui/mcp) 도 kebab-parse-code 를 직접 의존하지 않음 — 경계 구조 전체가 설계 의도와 일치.
@@ -0,0 +249,4 @@
units.push((format!("{prefix}{name}!"), s, e, true));
}
}
"impl_item" => {

edge case 미문서화 — fn 없는 impl 블록 전체 누락: impl_item arm 은 body 안의 function_item 만 units 에 추가하고, 해당 impl 블록 자체는 glue 에도 units 에도 들어가지 않음 (flush_glue 후 units.push 없이 종료). 결과적으로 impl Default for Foo { ... } 처럼 fn 이 없는 (const / type 만 있는) impl 블록은 색인에서 완전 누락됨 — 이는 의도된 1A scope 제한이지만 현재 테스트에 없음. module-level doc comment (//!) 에 언급되지도 않음. 적어도 file-level doc comment 에 한 줄 추가하거나, extract_inline 테스트에 impl Display for X { fn fmt(…) {} } vs impl Default for X {} 케이스를 추가해 의도를 명시하는 것을 권장.

**edge case 미문서화 — fn 없는 impl 블록 전체 누락**: `impl_item` arm 은 body 안의 `function_item` 만 units 에 추가하고, 해당 impl 블록 자체는 glue 에도 units 에도 들어가지 않음 (`flush_glue` 후 units.push 없이 종료). 결과적으로 `impl Default for Foo { ... }` 처럼 fn 이 없는 (`const` / `type` 만 있는) impl 블록은 색인에서 완전 누락됨 — 이는 의도된 1A scope 제한이지만 현재 테스트에 없음. module-level doc comment (//!) 에 언급되지도 않음. 적어도 file-level doc comment 에 한 줄 추가하거나, `extract_inline` 테스트에 `impl Display for X { fn fmt(…) {} }` vs `impl Default for X {}` 케이스를 추가해 의도를 명시하는 것을 권장.
@@ -95,6 +98,7 @@ flowchart TB
ppdf --> ptypes
pimg --> ptypes
paud --> ptypes
pcode --> ptypes

버그 — 존재하지 않는 의존성 에지: pcode --> ptypes 가 Mermaid 다이어그램에 추가됐지만 cargo tree -p kebab-parse-code --depth 1 결과에 kebab-parse-types 가 없음. 실제로 kebab-parse-code 는 kebab-core 를 직접 의존하고 kebab-parse-types 는 의존하지 않음 (다른 parse-* crate 들은 ptypes 를 거침). 이 에지는 제거해야 함.

**버그 — 존재하지 않는 의존성 에지**: `pcode --> ptypes` 가 Mermaid 다이어그램에 추가됐지만 `cargo tree -p kebab-parse-code --depth 1` 결과에 `kebab-parse-types` 가 없음. 실제로 kebab-parse-code 는 kebab-core 를 직접 의존하고 kebab-parse-types 는 의존하지 않음 (다른 parse-* crate 들은 ptypes 를 거침). 이 에지는 제거해야 함.
@@ -168,6 +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)

nit — 설명 오류: directory tree 에 kebab-parse-code 항목이 # tree-sitter Rust AST extractor + code-rust-ast-v1 chunker (P10-1A-2) 로 기재됨. code-rust-ast-v1 chunker 는 kebab-chunk 소속 (crates/kebab-chunk/src/code_rust_ast_v1.rs) 이므로 여기에 포함시키면 혼란을 야기함. # tree-sitter Rust AST extractor (P10-1A-2) 로 줄이고 kebab-chunk 항목에 code-rust-ast-v1 이미 추가됐으니 충분.

**nit — 설명 오류**: directory tree 에 `kebab-parse-code` 항목이 `# tree-sitter Rust AST extractor + code-rust-ast-v1 chunker (P10-1A-2)` 로 기재됨. `code-rust-ast-v1` chunker 는 `kebab-chunk` 소속 (`crates/kebab-chunk/src/code_rust_ast_v1.rs`) 이므로 여기에 포함시키면 혼란을 야기함. `# tree-sitter Rust AST extractor (P10-1A-2)` 로 줄이고 kebab-chunk 항목에 `code-rust-ast-v1` 이미 추가됐으니 충분.
docs/SMOKE.md Outdated
@@ -305,0 +313,4 @@
# 2) ingest — .rs 가 code-rust-ast-v1 로 처리됨
KB ingest
# 3) 결과 검증 — IngestReport.items 에 .rs 자산이 "new" 로 분류, parser_version = "code-rust-ast-v1"

버그 — parser_version 문자열 오류: 주석에 parser_version = "code-rust-ast-v1" 으로 기재되어 있지만, 실제 상수는 crates/kebab-parse-code/src/rust.rspub const PARSER_VERSION: &str = "code-rust-v1"; 임. chunker_version = "code-rust-ast-v1" 과 혼동된 것으로 보임. smoke 실행 시 이 주석을 따라 확인하면 틀린 값을 기대하게 되므로 수정 필요: parser_version = "code-rust-v1".

**버그 — parser_version 문자열 오류**: 주석에 `parser_version = "code-rust-ast-v1"` 으로 기재되어 있지만, 실제 상수는 `crates/kebab-parse-code/src/rust.rs` 의 `pub const PARSER_VERSION: &str = "code-rust-v1";` 임. `chunker_version = "code-rust-ast-v1"` 과 혼동된 것으로 보임. smoke 실행 시 이 주석을 따라 확인하면 틀린 값을 기대하게 되므로 수정 필요: `parser_version = "code-rust-v1"`.
docs/SMOKE.md Outdated
@@ -305,0 +317,4 @@
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}]}'

버그 — jq path 오류: .citation.code_lang 는 존재하지 않는 필드. Citation::Code wire shape (kebab-core/src/citation.rs) 의 언어 필드는 lang — 즉 .citation.lang 이 올바름. SearchHit 에는 top-level .code_lang 이 있으나 그건 별도 필드. jq 표현을 {symbol: .citation.symbol, lang: .citation.lang, code_lang: .code_lang, repo: .repo} 로 수정하면 두 필드를 구분해서 확인 가능.

**버그 — jq path 오류**: `.citation.code_lang` 는 존재하지 않는 필드. `Citation::Code` wire shape (kebab-core/src/citation.rs) 의 언어 필드는 `lang` — 즉 `.citation.lang` 이 올바름. `SearchHit` 에는 top-level `.code_lang` 이 있으나 그건 별도 필드. jq 표현을 `{symbol: .citation.symbol, lang: .citation.lang, code_lang: .code_lang, repo: .repo}` 로 수정하면 두 필드를 구분해서 확인 가능.
docs/SMOKE.md Outdated
@@ -332,6 +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 가 색인됨.

nit — 같은 citation.code_lang 오류 재등장: 검증 체크리스트 항목에도 citation.code_lang = "rust" 라고 기재됨. 위 step 4 수정과 함께 여기도 citation.lang = "rust" 로 정정 필요.

**nit — 같은 citation.code_lang 오류 재등장**: 검증 체크리스트 항목에도 `citation.code_lang = "rust"` 라고 기재됨. 위 step 4 수정과 함께 여기도 `citation.lang = "rust"` 로 정정 필요.
altair823 added 1 commit 2026-05-19 23:24:25 +00:00
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) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-19 23:32:33 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — 회차 1 지적 7건 모두 반영 확인. 본 회차는 safety/correctness 관점에서 PR 전체를 재검토한 결과를 담습니다.

회차 1에서 수정된 항목을 diff 수준에서 직접 검증했습니다: SMOKE.md의 .citation.code_lang.citation.lang 세 곳 전부, parser_version = "code-rust-v1" 한 곳, ARCHITECTURE.md Mermaid의 pcode → ptypespcode → core 교체 및 디렉토리 트리 설명 정정, app.rs backfill_repotracing::warn! (target: "kebab-app", 비-abort 보존), rust.rs impl arm 상단 주석 추가 — 전부 의도대로 반영됨을 확인했습니다.

회차 2에서 발견된 주요 사항: README.md 명령 표의 citation 설명에서 동일 클래스의 오류(wire citation 필드명 혼동)가 잔존합니다. SMOKE.md의 [ingest.code] 설정 블록 참조 설명에 항목 누락이 있습니다. 나머지 correctness 항목(chunk_id 충돌 가능성, HashMap 반복 순서 유출, try_skip_unchanged parity, 빈 파일 처리, unwrap 사용처)은 모두 안전함을 확인했습니다.

회차 2 — 회차 1 지적 7건 모두 반영 확인. 본 회차는 safety/correctness 관점에서 PR 전체를 재검토한 결과를 담습니다. 회차 1에서 수정된 항목을 diff 수준에서 직접 검증했습니다: SMOKE.md의 `.citation.code_lang` → `.citation.lang` 세 곳 전부, `parser_version = "code-rust-v1"` 한 곳, ARCHITECTURE.md Mermaid의 `pcode → ptypes` → `pcode → core` 교체 및 디렉토리 트리 설명 정정, `app.rs` `backfill_repo`의 `tracing::warn!` (target: "kebab-app", 비-abort 보존), `rust.rs` impl arm 상단 주석 추가 — 전부 의도대로 반영됨을 확인했습니다. 회차 2에서 발견된 주요 사항: README.md 명령 표의 citation 설명에서 동일 클래스의 오류(wire citation 필드명 혼동)가 잔존합니다. SMOKE.md의 `[ingest.code]` 설정 블록 참조 설명에 항목 누락이 있습니다. 나머지 correctness 항목(chunk_id 충돌 가능성, HashMap 반복 순서 유출, `try_skip_unchanged` parity, 빈 파일 처리, `unwrap` 사용처)은 모두 안전함을 확인했습니다.
@@ -3,3 +3,4 @@
.claude/
/target
/target/
**/*.rs.bk

[nit] /target 행이 추가되었지만 기존 /target/ 행과 중복입니다. git은 디렉토리에 대해 두 패턴을 동일하게 취급합니다. 어느 한 쪽을 제거하면 됩니다(기존 /target/ 유지가 자연스럽습니다).

**[nit]** `/target` 행이 추가되었지만 기존 `/target/` 행과 중복입니다. git은 디렉토리에 대해 두 패턴을 동일하게 취급합니다. 어느 한 쪽을 제거하면 됩니다(기존 `/target/` 유지가 자연스럽습니다).

[doc / correctness] 회차 1에서 SMOKE.md의 .citation.code_lang.citation.lang 세 곳을 모두 수정했는데, README 명령 표에서 동일 클래스의 오류가 잔존합니다.

현재: citation.kind = "code"symbol + code_lang = "rust" + repo (workspace root 상대) 포함

code_langSearchHit top-level 필드이고 repo도 마찬가지입니다. Citation wire 내부 필드명은 lang입니다 (Citation::Code { lang, symbol, line_start, line_end, path }). 현재 문장은 사용자가 citation.code_lang으로 jq를 작성하도록 오해를 유도합니다.

제안 수정: 코드 chunk 는 citation 에 symbol+lang = "rust"가 포함되고, SearchHit 최상위에code_lang = "rust"+repo (workspace root 상대) 가 함께 반환됨.

(SMOKE.md 검증 스크립트가 .citation.lang을 올바르게 사용하고 있으니 해당 표현에 맞추면 됩니다.)

**[doc / correctness]** 회차 1에서 SMOKE.md의 `.citation.code_lang` → `.citation.lang` 세 곳을 모두 수정했는데, README 명령 표에서 동일 클래스의 오류가 잔존합니다. 현재: `citation.kind = "code"` 에 `symbol` + `code_lang = "rust"` + `repo` (workspace root 상대) 포함 `code_lang`은 `SearchHit` top-level 필드이고 `repo`도 마찬가지입니다. Citation wire 내부 필드명은 `lang`입니다 (`Citation::Code { lang, symbol, line_start, line_end, path }`). 현재 문장은 사용자가 `citation.code_lang`으로 jq를 작성하도록 오해를 유도합니다. 제안 수정: `코드 chunk 는 citation 에 `symbol` + `lang = "rust"` 가 포함되고, SearchHit 최상위에 `code_lang = "rust"` + `repo` (workspace root 상대) 가 함께 반환됨.` (SMOKE.md 검증 스크립트가 `.citation.lang`을 올바르게 사용하고 있으니 해당 표현에 맞추면 됩니다.)
@@ -0,0 +55,4 @@
fn extract(
&self,
ctx: &kebab_core::ExtractContext<'_>,
bytes: &[u8],

[edge-case / nit] line_comment / block_comment 노드는 walk() 내부 match 에서 어느 arm 에도 해당하지 않아 _ => {} (no-op)로 처리됩니다. 즉 주석만 담긴 Rust 파일(또는 빈 파일)은 블록이 하나도 생성되지 않아 ingest 후 chunk_count = 0으로 기록되고 검색에 surface 되지 않습니다.

동작 자체는 합리적(의미 단위 없는 파일은 검색 대상 외)이고 빈 파일의 경우도 tree-sitter 가 정상 파싱하므로 패닉은 없습니다. 다만 이 동작은 어디에도 문서화되어 있지 않아 향후 기여자가 버그로 오인할 수 있습니다.

build_blocks 함수 상단이나 모듈 doc-comment에 한 줄 추가를 제안합니다: // A comment-only or empty file produces zero blocks (no semantic units).

**[edge-case / nit]** `line_comment` / `block_comment` 노드는 `walk()` 내부 match 에서 어느 arm 에도 해당하지 않아 `_ => {}` (no-op)로 처리됩니다. 즉 주석만 담긴 Rust 파일(또는 빈 파일)은 블록이 하나도 생성되지 않아 ingest 후 `chunk_count = 0`으로 기록되고 검색에 surface 되지 않습니다. 동작 자체는 합리적(의미 단위 없는 파일은 검색 대상 외)이고 빈 파일의 경우도 tree-sitter 가 정상 파싱하므로 패닉은 없습니다. 다만 이 동작은 어디에도 문서화되어 있지 않아 향후 기여자가 버그로 오인할 수 있습니다. `build_blocks` 함수 상단이나 모듈 doc-comment에 한 줄 추가를 제안합니다: `// A comment-only or empty file produces zero blocks (no semantic units).`

[doc / nit] [ingest.code] 설정 (config.toml 에 이미 포함됨 — 위 격리 config 블록 참조) 라고 하지만, 위 격리 config 블록(smoke setup 절의 toml 예시)에는 skip_generated_header / max_file_bytes / max_file_lines 세 항목만 있습니다. 바로 아래에 보여주는 4항목 블록의 extra_skip_globs = []는 격리 config 블록에 없는 항목입니다.

extra_skip_globs의 기본값이 []이라 동작에는 문제 없지만, 독자가 「격리 config에 이미 포함됐다고 했는데 내 파일엔 없네?」 하고 혼동할 수 있습니다. 아래 두 가지 중 하나로 해결하면 됩니다:

  1. 격리 config 블록에 extra_skip_globs = [] 행을 추가하거나,
  2. 이 절의 서술을 "기본값 확인용 참고 블록" 임을 명시하도록 수정 (예: 기본값 참조 — 필요한 경우 config.toml 에 추가).
**[doc / nit]** `[ingest.code]` 설정 (config.toml 에 이미 포함됨 — 위 격리 config 블록 참조) 라고 하지만, 위 격리 config 블록(smoke setup 절의 toml 예시)에는 `skip_generated_header` / `max_file_bytes` / `max_file_lines` 세 항목만 있습니다. 바로 아래에 보여주는 4항목 블록의 `extra_skip_globs = []`는 격리 config 블록에 없는 항목입니다. `extra_skip_globs`의 기본값이 `[]`이라 동작에는 문제 없지만, 독자가 「격리 config에 이미 포함됐다고 했는데 내 파일엔 없네?」 하고 혼동할 수 있습니다. 아래 두 가지 중 하나로 해결하면 됩니다: 1. 격리 config 블록에 `extra_skip_globs = []` 행을 추가하거나, 2. 이 절의 서술을 "기본값 확인용 참고 블록" 임을 명시하도록 수정 (예: `기본값 참조 — 필요한 경우 config.toml 에 추가`).
altair823 added 1 commit 2026-05-19 23:35:05 +00:00
PR #140 회차 2 actionable 4건:
- README.md: `citation.kind = "code"` 행에서 wire 필드 구조 정정 — citation 안에는 `lang`, SearchHit top-level 에는 `code_lang`/`repo` (round 1 SMOKE 정정과 동일 클래스)
- docs/SMOKE.md: 격리 config 블록에 `extra_skip_globs = []` 추가 (P10 섹션의 "위 격리 config 블록 참조" 와 정합)
- crates/kebab-parse-code/src/rust.rs: comment-only 파일 → 0 blocks 동작을 module doc 에 한 줄 명시 (pdf-page-v1 의 "empty page produces no chunks" 패턴과 동일)
- .gitignore: `/target/` 제거 — `/target` (no trailing slash) 이 디렉토리 + 파일 + 심링크 모두 매칭하므로 `/target/` (dir 전용) 는 redundant

verify: `cargo check -p kebab-parse-code` clean (주석/문서 외 영향 없음).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-19 23:39:25 +00:00
claude-reviewer-01 left a comment
Member

회차 3 — 회차 2 수정 4건 모두 확인 완료 (README wire 필드 구조, SMOKE 격리 config extra_skip_globs, rust.rs edge-case doc comment, .gitignore /target dedup). 신규 actionable 없음 — 교차 문서 버전 일관성 (0.7.0, code-rust-ast-v1, code-rust-v1, HOTFIXES 날짜 2026-05-19) 전부 정합, tracing::warn 는 실제 DB 오류 시에만 발생 (정상 검색 시 무음), jq 예시 및 wire 필드 표현 정확. APPROVE.

회차 3 — 회차 2 수정 4건 모두 확인 완료 (README wire 필드 구조, SMOKE 격리 config `extra_skip_globs`, rust.rs edge-case doc comment, `.gitignore` `/target` dedup). 신규 actionable 없음 — 교차 문서 버전 일관성 (`0.7.0`, `code-rust-ast-v1`, `code-rust-v1`, HOTFIXES 날짜 `2026-05-19`) 전부 정합, `tracing::warn` 는 실제 DB 오류 시에만 발생 (정상 검색 시 무음), jq 예시 및 wire 필드 표현 정확. APPROVE.
@@ -780,0 +808,4 @@
/// Non-repo documents (markdown, PDF, plain text, code files outside a
/// git tree) correctly keep `repo: None` — `Metadata.repo` is already
/// `None` for those, so the assignment is a no-op.
fn backfill_repo(&self, hits: &mut [SearchHit]) {

HashMap<DocumentId, Option<String>> dedup 캐시로 동일 doc 의 중복 store 쿼리를 방지하고, Ok(None) 케이스 (repo 없는 문서) 도 캐시에 기록해 re-query 를 회피하는 설계가 깔끔합니다. Err 분기에서 tracing::warn 을 남기고 검색 응답 전체는 abort 하지 않는 non-aborting 정책도 review round 1 피드백을 정확히 반영했습니다.

`HashMap<DocumentId, Option<String>>` dedup 캐시로 동일 doc 의 중복 store 쿼리를 방지하고, `Ok(None)` 케이스 (repo 없는 문서) 도 캐시에 기록해 re-query 를 회피하는 설계가 깔끔합니다. `Err` 분기에서 `tracing::warn` 을 남기고 검색 응답 전체는 abort 하지 않는 non-aborting 정책도 review round 1 피드백을 정확히 반영했습니다.
@@ -0,0 +153,4 @@
/// gluing paragraphs until ~`AST_CHUNK_MAX_LINES` lines accumulate.
/// Returns `(line_offset_start, line_offset_end, text)` where offsets are
/// 0-based within the unit (caller adds the unit's absolute `line_start`).
fn split_oversize(code: &str) -> Vec<(u32, u32, String)> {

split_oversize + [part i/N] 명명 패턴이 깔끔합니다. oversize 블록을 blank-line 경계에서 분리하고 part_ls = ls + off_start 로 원본 line 번호를 정확하게 보존하는 구현이 design §9.1 의 의도를 충실히 반영합니다.

split_oversize + [part i/N] 명명 패턴이 깔끔합니다. oversize 블록을 blank-line 경계에서 분리하고 `part_ls = ls + off_start` 로 원본 line 번호를 정확하게 보존하는 구현이 design §9.1 의 의도를 충실히 반영합니다.
altair823 merged commit 73e5b359d8 into main 2026-05-19 23:40:19 +00:00
altair823 deleted branch feat/p10-1a-2-rust-ast-chunker 2026-05-19 23:40:21 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#140