(1) tasks/HOTFIXES.md: add 2026-05-20 entry for path-sanitize gap in
module_path_for_python / _tsjs (promised in task spec line 55 but
not landed in round 0). Bidirectional cross-link added.
(2) crates/kebab-parse-code: dedup filename_from_workspace_path /
strip_extension / join_symbol via new pub(crate) module scaffold.rs.
Removed 9 byte-identical fn copies across rust/python/typescript/
javascript extractors. Pure refactor — no behavior change.
(3) crates/kebab-parse-code/tests/fixtures/sample.py: @staticmethod was
semantically inappropriate on a module-level fn (class-method
decorator). Changed to @no_type_check; test assertion updated.
(5)+(6) crates/kebab-parse-code/src/lang.rs: add tests/test_foo.py case
to module_path_for_python test + doc clarifying that tests/ /
examples/ / benches/ are intentionally not stripped.
(4) PUSH BACK — TS/JS class decorator handling is design intent of 1B
1차 (typescript.rs:242-244 + HOTFIXES entry 2 already in place).
No code change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.8 KiB
p10-1B — Python + TS/JS AST chunkers
Status: 🟡 진행 중
Contract sections: §3.3 (chunker_version code-python-ast-v1 / code-ts-ast-v1 / code-js-ast-v1), §3.4 (symbol path — Python pkg.module.Class.method, TS/JS module/Class.method / module/default), §3.5 (code_lang python / typescript / javascript), §5 (확장자 라우팅 활성화), §6.1 (kebab-parse-code/src/{python,typescript,javascript}.rs), §6.2 (kebab-chunk/src/code_{python,ts,js}_ast_v1.rs), §9.1 (Tier 1 AST per-language + oversize fallback).
Design: 2026-05-15-kebab-code-ingest-design.md §1B.
Plan: 2026-05-20-p10-1b-py-ts-js-ast-chunkers.md.
Goal
1A-2 가 깐 인프라 (SourceSpan::Code, MediaType::Code(String), Citation::Code 매핑, citation_helper arm, backfill_code_lang + backfill_repo, schema.v1.code_lang_breakdown, [ingest.code] 절, HOTFIXES) 위에 Python + TypeScript + JavaScript 3 언어의 extractor + chunker 를 활성화. design §1B 묶음과 일치하는 단일 PR. 머지 시점부터 Python / TS / JS 프로젝트도 dogfooding 가능.
동결된 설계 결정 (이 task 로 확정)
- Symbol path 의 module prefix = workspace 경로 → module path 변환 (design §3.4 예시 충실, 사용자 명시 결정):
- Python:
crates/x/src/foo/bar.py같은 workspace_path 를//__init__.py처리 +.py·.pyistrip +/→.변환 후 dotted prefix 로 사용. 예시:kebab_eval/metrics.py의def compute_mrr()→ symbolkebab_eval.metrics.compute_mrr.pkg/__init__.py는 modulepkg자체. 변환은kebab-parse-code::lang::module_path_for_python(workspace_path)단일 함수 (source of truth). - TS/JS:
src/search/retriever/Retriever.ts→src/search/retriever/Retrieverprefix +/구분자 보존 +.ts/.tsx/.js/.jsx/.mjs/.cjsstrip. 예시:src/search/retriever/Retriever.ts의 methodsearch→src/search/retriever/Retriever.search.module/default는export default function/class경우. 변환은module_path_for_tsjs(workspace_path). - Rust 1A-2 는 retrofit 하지 않음 — 1A 는 file-scope nesting 만 사용 (workspace prefix 없음). 비일관 수용; HOTFIXES 2026-05-20 에 기록 + 사용자가 명시 요청 시 retrofit (chunker_version bump + re-ingest cascade 필요).
- Python:
- TypeScript grammar selection:
tree-sitter-typescriptcrate 의LANGUAGE_TYPESCRIPT는.ts,LANGUAGE_TSX는.tsx에 사용. 파일 확장자로 선택.code-ts-ast-v1하나의 chunker 가 둘 다 처리 (parser_versioncode-ts-v1). - JavaScript grammar:
tree-sitter-javascript단일 LanguageFn 가.js/.mjs/.cjs/.jsx모두 처리. 별도 분기 불필요. - Expression-level 함수 (arrow fn / function expression assigned to const): 1B 1차에서는 declaration-level 만 unit (function_declaration / class_declaration / method_definition / interface_declaration / type_alias_declaration / decorated_definition 등).
const foo = () => {...}같은 expression-level 은 glue 로 잡힘. HOTFIXES 2026-05-20 기록; 후속 phase 에서 lexical_declaration 안의 함수 표현식 unwrap 추가 검토. - App dispatch 일반화: 현재
ingest_one_code_asset은 RustAstExtractor + CodeRustAstV1Chunker 하드코딩. 1B 에서lang: &str받아 dispatch (Rust 도 동일 함수로 흡수) — Extractor 와 Chunker 를 trait object 가 아니라 enum/match 로 선택 (kebab-app 만 변경, kebab-core/Chunker trait 불변). frozen design 영향 없음. - frozen design 자체는 변경 없음 (§3.4 의 symbol path 예시는 이미 본 결정과 일치). §10.1 (post-merge surface) 에 1B 활성화 한 줄 추가.
Acceptance criteria
cargo test --workspace --no-fail-fast -j 1passes (메모리 의식적으로는 per-crate; full-suite gate 는 Task K 직전 1회).cargo clippy --workspace --all-targets -- -D warningspasses.- 3 언어 각각의 fixture (
tests/fixtures/sample.{py,ts,js}) ingest → chunk snapshot 안정 +Citation::Code의 symbol/line 이 §3.4 컨벤션 (workspace path → module path) 과 일치. - 격리 TempDir KB 에 Python/TS/JS 파일 하나씩 두고
kebab search --code-lang {python|typescript|javascript} --json가 정상 결과 반환. kebab schema --json | jq .stats.code_lang_breakdown에python,typescript,javascript카운트 등장.- README + HANDOFF + ARCHITECTURE + SMOKE + tasks/INDEX + tasks/p10/INDEX 갱신.
- frozen design §10.1 한 줄 추가 (1B 활성화).
- HOTFIXES 2026-05-20 에 (a) Rust 1A-2 symbol path 비일관 (1B 와 다름), (b) expression-level 함수 단위 제외 — 두 편차 기록.
- workspace
Cargo.tomlminor bump (0.7.0 → 0.8.0) — 도그푸딩 가능 surface 확장.
Allowed dependencies
kebab-parse-code에tree-sitter-python,tree-sitter-typescript,tree-sitter-javascript추가 (workspace deps 경유). 기존kebab-core/anyhow/gix/tree-sitter/tree-sitter-rust/serde_json/time/tracing유지.kebab-chunk의 새 모듈 3개 (code_python_ast_v1.rs/code_ts_ast_v1.rs/code_js_ast_v1.rs) — 1A-2 chunker 와 동일 dep (kebab-core + serde_json_canonicalizer + blake3 + anyhow + tracing). tree-sitter 절대 import 금지.kebab-app변경 — 새 crate dep 없음.kebab-source-fs— 확장자 추가만, 새 dep 없음.
Forbidden dependencies
kebab-chunk가tree-sitter-*직접 import 금지 (AST 는 parser-side).- UI crate (cli / mcp / tui) 가
kebab-parse-code직접 import 금지. kebab-parse-code가 store / embed / llm / rag 직접 import 금지 (design §8 inheritance).
Risks / notes
- tree-sitter-typescript 의
LANGUAGE_TYPESCRIPT와LANGUAGE_TSX가 별도 LanguageFn — 잘못 선택하면 TSX JSX 가 parse 실패. 파일 확장자 기반 선택을 단일 함수에서 결정 (테스트로 고정). - tree-sitter-python 의
decorated_definition노드 처리 — 데코레이터가 wrap 하는 형태라function_definition/class_definition가 child. unwrap 필요 (decorator 라인은 unit_start backward extension 으로 자연스럽게 포함됨). - Python
pkg/__init__.py의 module path =pkg자체 (basename 제거).module_path_for_python가 이걸 처리. - TS/JS 의
export default function/class— name 이 없을 수 있음 (export default function () {...}). symbolmodule/default로 표기 (design §3.4). module_path_for_python/module_path_for_tsjs가 workspace_path 의 비-ASCII / 공백 / 특수문자 처리 필요. 1B 1차에서는 그대로 전달 (sanitize 없음); HOTFIXES 에 path-sanitize 부재 기록.- 1A-2
ingest_one_code_asset일반화로 인한 dispatch 코드 변경 — Rust 기존 동작 byte-identical 유지를 통합 테스트로 확인. - 머지 후 deviation 은
tasks/HOTFIXES.md에 dated 로그 + 본 specRisks / notes에 one-line cross-link. - [HOTFIXES 2026-05-20] Rust 1A-2 symbol 은 file-scope nesting 만 (workspace prefix 없음); 1B 의 Python/TypeScript/JavaScript 와 비일관 — retrofit 은 사용자 명시 요청 시. 자세한 내용:
tasks/HOTFIXES.md(2026-05-20, "Rust 1A-2 symbol path"). - [HOTFIXES 2026-05-20] TypeScript/JavaScript 의 expression-level 함수 (
const foo = () => {}등) 는<top-level>glue 로 처리됨, 독립 unit 미방출 — 후속 phase 에서lexical_declarationunwrap 검토. 자세한 내용:tasks/HOTFIXES.md(2026-05-20, "expression-level functions"). - [HOTFIXES 2026-05-20]
module_path_for_python/module_path_for_tsjs가 path-sanitize 안 함 (특수문자/공백 그대로 prefix 에 들어감) — 후속 phase 에서 NFKC + 사용금지 문자 변환 검토. 자세한 내용:tasks/HOTFIXES.md(2026-05-20, "module_path_for_python / _tsjs do not sanitize").