feat(fb-31): single-file / stdin ingest — agent on-demand 저장 #111

Merged
altair823 merged 16 commits from feat/p9-fb-31-single-file-stdin-ingest into main 2026-05-07 09:56:11 +00:00
Owner

요약

  • kebab ingest-file <path> + kebab ingest-stdin --title <T> 신규 subcommand 2개. agent (Claude Code via MCP) / 사람 사용자 모두 단일 외부 file 또는 stdin 본문을 KB 에 저장.
  • MCP tool ingest_file + ingest_stdin 추가 (4 → 6). fb-30 v1 read-only 정책 변경 — 첫 mutation surface (의도된 진화).
  • 기존 kebab ingest (전체 walk) 무영향.

변경 사항

feat/p9-fb-31-single-file-stdin-ingest 14 commits, 24 files (+1121/-13).

새 모듈 / facade

  • crates/kebab-app/src/external.rs (신규) — ensure_external_dir, ensure_kebabignore_entry (idempotent + 누락 trailing newline 처리), copy_to_external (blake3 12-prefix 명명, idempotent), inject_frontmatter (YAML 더블쿼트 escape, --- 시작 시 error). 14 unit tests.
  • kebab-app::ingest_file_with_config(cfg, &Path) (신규 facade) — _external/<hash12>.<ext> copy + .kebabignore 자동 line append + 단일 asset 으로 기존 ingest_with_config_opts 재사용 (SourceScope include filter).
  • kebab-app::ingest_stdin_with_config(cfg, body, title, source_uri) (신규 facade) — inject_frontmatteringest_file_with_config 위임.
  • 두 facade 모두 #[doc(hidden)] pub fn (CLAUDE.md 의 *_with_config 컨벤션 준수).

CLI 변경

  • Cmd::IngestFile { path: PathBuf } + arm.
  • Cmd::IngestStdin { title: String, source_uri: Option<String> } + arm + stdin read.

MCP 변경

  • crates/kebab-mcp/src/tools/ingest_file.rs + ingest_stdin.rs 신규.
  • build_tools_vec() 4 → 6, call_tool 두 신규 arm (spawn_tool helper 재사용).
  • KebabAppState::config_path 활용해 doctor tool 과 동일 path-aware 동작.

_external/ policy

  • 위치: <workspace.root>/_external/. 첫 ingest-file / ingest-stdin 시 자동 생성.
  • 명명: <blake3-12>.<ext> deterministic — 동일 content 재 ingest 면 idempotent (incremental ingest 가 unchanged 처리).
  • .kebabignore 첫 생성 시 _external/ line 자동 append (walk re-ingestion 무한 루프 방지).
  • .kebabignore 매치 시 stderr warn 후 진행 (explicit ingest = bypass intent, 별 --force-ignore flag 불필요).

Wire schema 영향

없음. 모두 기존 schema 재사용 (ingest_report.v1 / error.v1). source_uri 는 frontmatter → Document.metadata free-form map 자동 흐름.

테스트

  • 신규 ~22 테스트 (kebab-app external 14 unit + integration 3+3, kebab-cli 2 spawn-based, kebab-mcp 2+2).
  • cargo clippy --workspace --all-targets -- -D warnings clean.
  • cargo test --workspace -j 1 — fb-31 신규 테스트 모두 PASS. 2 reset.rs 실패는 pre-existing env-dependent (XDG_CONFIG_HOME) — fb-31 무관.
  • Manual smoke (/tmp/kebab-fb31-final): ingest-file + ingest-stdin 모두 new=1, _external/ 2 files, .kebabignore _external/ line, MCP tools/list 6 tools.

Spec contract

  • design §6 에 _external/ subdirectory 절 추가 (실제 §6.7 — 기존 §6 sub-section 이 6.6 까지 채워져 있어 §6.7 위치, spec stub 의 §6.3 명시는 deviation, HOTFIXES 명시).
  • task spec tasks/p9/p9-fb-31-single-file-stdin-ingest.md status opencompleted.
  • spec stub 의 --media flag → 실제 v1 markdown only (deviation 없음 — spec 자체에 markdown 전용 명시).
  • fb-30 v1 read-only MCP 정책 → fb-31 mutation surface 도입 (의도된 진화, HOTFIXES 명시).

Release trigger (impl PR 머지 후)

별 PR — 0.3.1 → 0.3.2 patch (chore/bump-v0.3.2 branch + PR + gitea-release v0.3.2). fb-27 / fb-30 precedent 동일.

surface 추가 (신규 subcommand + 신규 MCP tool) 지만 wire schema 변경 없고 backwards-compat 완전 — pre-1.0 patch policy 일관 (fb-30 도 0.3.1 patch 였음).

Final review fixes (commit dc24cb3)

  • ingest_stdin_with_config#[doc(hidden)] 추가 (CLAUDE.md 컨벤션).
  • SKILL.md Since v0.4.0Since v0.3.1 (실제 MCP shipped in fb-30 release).
  • MCP tools_call_ingest_file idempotency test 추가 (spec 의 2 test 요구 사항 충족).
## 요약 - **`kebab ingest-file <path>`** + **`kebab ingest-stdin --title <T>`** 신규 subcommand 2개. agent (Claude Code via MCP) / 사람 사용자 모두 단일 외부 file 또는 stdin 본문을 KB 에 저장. - **MCP tool `ingest_file` + `ingest_stdin`** 추가 (4 → 6). fb-30 v1 read-only 정책 변경 — 첫 mutation surface (의도된 진화). - 기존 `kebab ingest` (전체 walk) 무영향. ## 변경 사항 `feat/p9-fb-31-single-file-stdin-ingest` 14 commits, 24 files (+1121/-13). ### 새 모듈 / facade - **`crates/kebab-app/src/external.rs`** (신규) — `ensure_external_dir`, `ensure_kebabignore_entry` (idempotent + 누락 trailing newline 처리), `copy_to_external` (blake3 12-prefix 명명, idempotent), `inject_frontmatter` (YAML 더블쿼트 escape, `---` 시작 시 error). 14 unit tests. - **`kebab-app::ingest_file_with_config(cfg, &Path)`** (신규 facade) — `_external/<hash12>.<ext>` copy + `.kebabignore` 자동 line append + 단일 asset 으로 기존 `ingest_with_config_opts` 재사용 (SourceScope include filter). - **`kebab-app::ingest_stdin_with_config(cfg, body, title, source_uri)`** (신규 facade) — `inject_frontmatter` 후 `ingest_file_with_config` 위임. - 두 facade 모두 `#[doc(hidden)] pub fn` (CLAUDE.md 의 `*_with_config` 컨벤션 준수). ### CLI 변경 - `Cmd::IngestFile { path: PathBuf }` + arm. - `Cmd::IngestStdin { title: String, source_uri: Option<String> }` + arm + stdin read. ### MCP 변경 - `crates/kebab-mcp/src/tools/ingest_file.rs` + `ingest_stdin.rs` 신규. - `build_tools_vec()` 4 → 6, `call_tool` 두 신규 arm (spawn_tool helper 재사용). - `KebabAppState::config_path` 활용해 doctor tool 과 동일 path-aware 동작. ### `_external/` policy - 위치: `<workspace.root>/_external/`. 첫 ingest-file / ingest-stdin 시 자동 생성. - 명명: `<blake3-12>.<ext>` deterministic — 동일 content 재 ingest 면 idempotent (incremental ingest 가 unchanged 처리). - `.kebabignore` 첫 생성 시 `_external/` line 자동 append (walk re-ingestion 무한 루프 방지). - `.kebabignore` 매치 시 stderr warn 후 진행 (explicit ingest = bypass intent, 별 `--force-ignore` flag 불필요). ### Wire schema 영향 **없음**. 모두 기존 schema 재사용 (`ingest_report.v1` / `error.v1`). source_uri 는 frontmatter → `Document.metadata` free-form map 자동 흐름. ## 테스트 - 신규 ~22 테스트 (kebab-app external 14 unit + integration 3+3, kebab-cli 2 spawn-based, kebab-mcp 2+2). - `cargo clippy --workspace --all-targets -- -D warnings` clean. - `cargo test --workspace -j 1` — fb-31 신규 테스트 모두 PASS. 2 reset.rs 실패는 pre-existing env-dependent (XDG_CONFIG_HOME) — fb-31 무관. - Manual smoke (`/tmp/kebab-fb31-final`): ingest-file + ingest-stdin 모두 new=1, `_external/` 2 files, `.kebabignore` `_external/` line, MCP tools/list 6 tools. ## Spec contract - design §6 에 `_external/` subdirectory 절 추가 (실제 §6.7 — 기존 §6 sub-section 이 6.6 까지 채워져 있어 §6.7 위치, spec stub 의 §6.3 명시는 deviation, HOTFIXES 명시). - task spec `tasks/p9/p9-fb-31-single-file-stdin-ingest.md` status `open` → `completed`. - spec stub 의 `--media` flag → 실제 v1 markdown only (deviation 없음 — spec 자체에 markdown 전용 명시). - fb-30 v1 read-only MCP 정책 → fb-31 mutation surface 도입 (의도된 진화, HOTFIXES 명시). ## Release trigger (impl PR 머지 후) 별 PR — **0.3.1 → 0.3.2 patch** (`chore/bump-v0.3.2` branch + PR + `gitea-release v0.3.2`). fb-27 / fb-30 precedent 동일. surface 추가 (신규 subcommand + 신규 MCP tool) 지만 wire schema 변경 없고 backwards-compat 완전 — pre-1.0 patch policy 일관 (fb-30 도 0.3.1 patch 였음). ## Final review fixes (commit `dc24cb3`) - `ingest_stdin_with_config` 에 `#[doc(hidden)]` 추가 (CLAUDE.md 컨벤션). - SKILL.md `Since v0.4.0` → `Since v0.3.1` (실제 MCP shipped in fb-30 release). - MCP `tools_call_ingest_file` idempotency test 추가 (spec 의 2 test 요구 사항 충족).
altair823 added 14 commits 2026-05-07 09:42:25 +00:00
Pure-fn helpers for the `_external/` workspace subdirectory:
- `ensure_external_dir(workspace_root)` — mkdir if absent
- `ensure_kebabignore_entry(workspace_root)` — append `_external/` line
  to .kebabignore if missing (idempotent)
- `copy_to_external(ext_dir, bytes, ext)` — write to
  `<ext_dir>/<blake3-12>.<ext>`, idempotent on same content
- `inject_frontmatter(body, title, source_uri?)` — prepend YAML block
  with strict double-quote escaping; errors if body already starts
  with `---`
- `yaml_quote(s)` — defensive escaping for agent-supplied strings

14 unit tests cover happy + idempotency + edge (CRLF frontmatter
detection, YAML escape).

ingest_file / ingest_stdin facades (Tasks 2-5) compose these.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single-file ingest entry. Copies bytes to _external/<hash12>.<ext>
via crate::external::copy_to_external, runs the per-medium pipeline on
that single asset (reuses ingest_with_config_opts via a SourceScope
{ root: _external/, include: [<filename>], exclude:
config.workspace.exclude }).

`.kebabignore` matches log a stderr warn line and proceed (explicit
ingest is bypass intent). Internal helper `check_kebabignore_match`
uses the `ignore` crate's GitignoreBuilder.

Returns the standard IngestReport (incremental ingest from fb-23
handles re-ingest as `unchanged`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three scenarios — copies external md + reports new=1, idempotent on
second call (unchanged=1), errors on missing path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wraps body with YAML frontmatter (title + source_uri) via
crate::external::inject_frontmatter, writes to
_external/<hash12>.md, delegates to ingest_file_with_config. Markdown
only in v1.

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>
5th + 6th MCP tools — first mutation surface (fb-30 v1 was read-only).
Both wrap the new kebab-app facade fns + use spawn_blocking via the
existing spawn_tool helper. tools/list now returns 6 tools.

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 명령 표 에 `kebab ingest-file` + `kebab ingest-stdin` 두 row + MCP tool list 4 → 6.
- HANDOFF post-도그푸딩 항목 한 줄.
- CLAUDE.md `_external/` 디렉토리 + naming convention 한 줄.
- integrations skill — Recipe D (agent fetched web doc) + MCP tool list 갱신.
- design §6.7 `_external/` subdirectory 절 신설.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fb-31 added ingest_file + ingest_stdin MCP tools (Task 9) but the
spawn-based smoke test in cli_mcp_smoke.rs still asserted the fb-30
count of 4. Bump to 6 to match the live tools/list response.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- kebab-app: add #[doc(hidden)] to ingest_stdin_with_config (CLAUDE.md
  convention — all *_with_config functions should have this attribute;
  fb-31's first impl missed it on the second facade fn).
- SKILL.md: "Since v0.4.0" → "Since v0.3.1" (MCP shipped in fb-30
  release v0.3.1; the wrong version claim was introduced in fb-30 doc
  sync and carried forward into fb-31).
- tools_call_ingest_file: add idempotency test (second call with same
  content → unchanged=1, new=0). Spec called for two tests; first impl
  shipped only the happy path.

Version bump 0.3.1 → 0.3.2 deferred to separate `chore/bump-v0.3.2` PR
mirroring fb-27 + fb-30 precedent (commits 73f5d73 / 5495d96).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-07 09:44:51 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — fb-31 직조 단단. 14 commit 의 layered story (external module + facade + tests + CLI + MCP + docs) 자연. facade rule 준수, spawn_tool 재사용, _external/ 정책 (deterministic blake3 명명 + .kebabignore auto-add idempotent + 누락 trailing newline 처리) 명확. fb-30 mutation surface 도입을 첫 PR 로 매끄럽게.

5 nit/follow-up:

  1. copy_to_external 의 ext lowercase normalize — caller-side 가 깔끔.
  2. ingest_file_with_config 의 unsupported extension early error — agent UX gap (현재 silent skip).
  3. ingest_stdin_with_config 의 ensure 3-helper 중복 호출 — defer 또는 주석.
  4. inject_frontmatter 의 두 검사 가독성 정리 — 단순화 옵션.
  5. inject_frontmatter doc 의 yaml_quote 처리 명시 — clarity.

테스트 커버리지 양호 (~22 신규), clippy clean, manual smoke 5 시나리오 정상. agent integration 다음 단계 (mutation tools) 으로 적합. 0.3.2 patch cut trigger 충족.

회차 1 — fb-31 직조 단단. 14 commit 의 layered story (external module + facade + tests + CLI + MCP + docs) 자연. facade rule 준수, spawn_tool 재사용, _external/ 정책 (deterministic blake3 명명 + .kebabignore auto-add idempotent + 누락 trailing newline 처리) 명확. fb-30 mutation surface 도입을 첫 PR 로 매끄럽게. 5 nit/follow-up: 1. `copy_to_external` 의 ext lowercase normalize — caller-side 가 깔끔. 2. `ingest_file_with_config` 의 unsupported extension early error — agent UX gap (현재 silent skip). 3. `ingest_stdin_with_config` 의 ensure 3-helper 중복 호출 — defer 또는 주석. 4. `inject_frontmatter` 의 두 검사 가독성 정리 — 단순화 옵션. 5. `inject_frontmatter` doc 의 yaml_quote 처리 명시 — clarity. 테스트 커버리지 양호 (~22 신규), clippy clean, manual smoke 5 시나리오 정상. agent integration 다음 단계 (mutation tools) 으로 적합. 0.3.2 patch cut trigger 충족.
@@ -0,0 +64,4 @@
) -> Result<PathBuf> {
let hash = blake3::hash(bytes);
let hex = hash.to_hex();
let prefix = &hex.as_str()[..12];

[normalize] ext 인자가 caller 의 path 에서 그대로 옴 — /tmp/file.PDF 면 ext = "PDF" (대문자). 결과 filename <hash>.PDF. 기존 ingest pipeline 의 extension 검사가 lowercase 가정한다면 silently skip 가능.

수정:

let ext = ext.to_lowercase();  // 첫 줄에 추가
let filename = format!("{prefix}.{ext}");

또는 caller (ingest_file_with_config) 에서 ext.to_lowercase() 후 전달. 후자는 ingest_stdin"md" literal 도 영향 안 받음. caller-side 가 더 깔끔.

**[normalize]** `ext` 인자가 caller 의 path 에서 그대로 옴 — `/tmp/file.PDF` 면 ext = `"PDF"` (대문자). 결과 filename `<hash>.PDF`. 기존 ingest pipeline 의 extension 검사가 lowercase 가정한다면 silently skip 가능. 수정: ```rust let ext = ext.to_lowercase(); // 첫 줄에 추가 let filename = format!("{prefix}.{ext}"); ``` 또는 caller (ingest_file_with_config) 에서 `ext.to_lowercase()` 후 전달. 후자는 `ingest_stdin` 의 `"md"` literal 도 영향 안 받음. caller-side 가 더 깔끔.
@@ -0,0 +83,4 @@
title: &str,
source_uri: Option<&str>,
) -> Result<String> {
if body.trim_start().starts_with("---\n") || body.trim_start().starts_with("---\r\n") {

[edge] inject_frontmattertrim_start().starts_with("---\n") + "---\r\n" 두 검사 — trim_start() 가 이미 모든 leading whitespace 제거하므로 첫 케이스 ("---\n") 와 두 번째 ("---\r\n") 모두 결과적으로 "---" 로 시작하면 매치.

실제로 두 검사 OR 가 정확히 같은 set 잡지는 않음 — "---a" 같은 "3 hyphen + non-newline" 케이스는 둘 다 false. 의도된 동작? frontmatter 의 canonical form 은 ---\n (또는 ---\r\n) 라 OK. 단순화 가능:

let head = body.trim_start();
if head.starts_with("---\n") || head.starts_with("---\r\n") || head.starts_with("---\r") {
    bail!(...)
}

or body.trim_start().lines().next() == Some("---") 로 더 명확. 현 코드 functional 정확 — 가독성 nit only.

**[edge]** `inject_frontmatter` 의 `trim_start().starts_with("---\n")` + `"---\r\n"` 두 검사 — `trim_start()` 가 이미 모든 leading whitespace 제거하므로 첫 케이스 (`"---\n"`) 와 두 번째 (`"---\r\n"`) 모두 결과적으로 `"---"` 로 시작하면 매치. 실제로 두 검사 OR 가 정확히 같은 set 잡지는 않음 — `"---a"` 같은 "3 hyphen + non-newline" 케이스는 둘 다 false. 의도된 동작? frontmatter 의 canonical form 은 `---\n` (또는 `---\r\n`) 라 OK. 단순화 가능: ```rust let head = body.trim_start(); if head.starts_with("---\n") || head.starts_with("---\r\n") || head.starts_with("---\r") { bail!(...) } ``` or `body.trim_start().lines().next() == Some("---")` 로 더 명확. 현 코드 functional 정확 — 가독성 nit only.
@@ -0,0 +87,4 @@
anyhow::bail!(
"stdin already has frontmatter; use `kebab ingest-file` for files with metadata"
);
}

[doc] inject_frontmatter doc 에 title YAML 처리 명시 권장 — agent 가 title: "He said \"hi\"" 같은 이상한 입력 넣을 때 internal escape 가 무엇 하는지 명시. 한 줄:

Internal yaml_quote always uses double-quoted YAML form with backslash escapes for " / \ / control chars — agent-supplied titles with special characters are safe.

별 task 아님 — doc clarity nit.

**[doc]** `inject_frontmatter` doc 에 title YAML 처리 명시 권장 — agent 가 `title: "He said \"hi\""` 같은 이상한 입력 넣을 때 internal escape 가 무엇 하는지 명시. 한 줄: > Internal `yaml_quote` always uses double-quoted YAML form with backslash escapes for `"` / `\` / control chars — agent-supplied titles with special characters are safe. 별 task 아님 — doc clarity nit.

[UX gap] ext 가 지원 안 되는 형식 (예 .docx / .txt / .epub) 일 때 silently 진행 → ingest pipeline 이 IngestReport.skipped_by_extension: {"docx": 1} 으로 카운트, new=0. agent 입장에서 "성공한 것 같은데 KB 에 안 들어감" 혼란.

명시적 early error 권장:

const SUPPORTED_EXTS: &[&str] = &["md", "pdf", "png", "jpg", "jpeg"];
let ext_lower = ext.to_lowercase();
if !SUPPORTED_EXTS.contains(&ext_lower.as_str()) {
    anyhow::bail!(
        "ingest-file: unsupported extension `.{}` (supported: {:?}); see kebab init for the canonical list",
        ext_lower, SUPPORTED_EXTS
    );
}

또는 fail-soft: warn + return IngestReport with skipped_by_extension. 본 PR 머지 차단 아님 — HOTFIXES Known-limitation 한 줄 추가도 OK.

**[UX gap]** ext 가 지원 안 되는 형식 (예 `.docx` / `.txt` / `.epub`) 일 때 silently 진행 → ingest pipeline 이 `IngestReport.skipped_by_extension: {"docx": 1}` 으로 카운트, `new=0`. agent 입장에서 "성공한 것 같은데 KB 에 안 들어감" 혼란. 명시적 early error 권장: ```rust const SUPPORTED_EXTS: &[&str] = &["md", "pdf", "png", "jpg", "jpeg"]; let ext_lower = ext.to_lowercase(); if !SUPPORTED_EXTS.contains(&ext_lower.as_str()) { anyhow::bail!( "ingest-file: unsupported extension `.{}` (supported: {:?}); see kebab init for the canonical list", ext_lower, SUPPORTED_EXTS ); } ``` 또는 fail-soft: warn + return `IngestReport` with skipped_by_extension. 본 PR 머지 차단 아님 — HOTFIXES Known-limitation 한 줄 추가도 OK.

[redundancy] ingest_stdin_with_configensure_external_dir + ensure_kebabignore_entry + copy_to_external 호출 후 ingest_file_with_config 위임 — 위임 함수도 같은 3 helper 호출. helper 3개 모두 idempotent 이라 functional 영향 없지만 stdin 호출 당 stat / file open / hash compute 가 두 번씩 발생.

간결화: stdin 은 wrapped string 만 만들고 그대로 임시 path 에 dump → ingest_file 위임. ingest_file 이 한 번만 ensure/copy. 또는 현 형태 유지하고 doc-comment 에 "intentional double-call (idempotency safe, ~ms overhead)" 명시.

현 v1 scale 에서 의미 있는 perf 차이 아님 — defer / 주석 추가 권장.

**[redundancy]** `ingest_stdin_with_config` 가 `ensure_external_dir` + `ensure_kebabignore_entry` + `copy_to_external` 호출 후 `ingest_file_with_config` 위임 — 위임 함수도 같은 3 helper 호출. helper 3개 모두 idempotent 이라 functional 영향 없지만 stdin 호출 당 stat / file open / hash compute 가 두 번씩 발생. 간결화: stdin 은 wrapped string 만 만들고 그대로 임시 path 에 dump → ingest_file 위임. ingest_file 이 한 번만 ensure/copy. 또는 현 형태 유지하고 doc-comment 에 "intentional double-call (idempotency safe, ~ms overhead)" 명시. 현 v1 scale 에서 의미 있는 perf 차이 아님 — defer / 주석 추가 권장.
altair823 added 1 commit 2026-05-07 09:47:05 +00:00
- ingest_file_with_config: lowercase normalize ext (caller-side) +
  early error on unsupported extension (`.docx` etc. now Err with
  helpful message instead of silent skipped_by_extension counter).
  New test ingest_file_errors_on_unsupported_extension.
- ingest_stdin_with_config: doc comment explaining intentional
  double-call of ensure helpers (idempotent + ~ms negligible).
- external::inject_frontmatter: simplify precheck via single
  trim_start binding + add CR-only line ending edge case.
- external::inject_frontmatter: doc note on yaml_quote escape
  contract (agent-supplied titles with special chars are safe).

Round 1 review summary: #111 (comment)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-07 09:47:41 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 2 — 회차 1 의 5 nit 모두 정확 반영. 추가 actionable 없음.

확인:

  1. ingest_file_with_config 의 ext lowercase normalize (caller-side, let ext = ext_raw.to_lowercase()).
  2. SUPPORTED_EXTS early bail (.docx 등) + 신규 test ingest_file_errors_on_unsupported_extension — agent UX gap 해소.
  3. ingest_stdin_with_config 의 의도된 double-call 명시 doc comment 추가.
  4. inject_frontmatterhead single binding + CR-only 케이스 추가.
  5. inject_frontmatter doc 의 yaml_quote escape contract 명시.

테스트 모두 통과 (external 14 unit + ingest_file 4 integration). clippy --workspace clean. 머지 가능.

회차 2 — 회차 1 의 5 nit 모두 정확 반영. 추가 actionable 없음. 확인: 1. `ingest_file_with_config` 의 ext lowercase normalize (caller-side, `let ext = ext_raw.to_lowercase()`). 2. `SUPPORTED_EXTS` early bail (`.docx` 등) + 신규 test `ingest_file_errors_on_unsupported_extension` — agent UX gap 해소. 3. `ingest_stdin_with_config` 의 의도된 double-call 명시 doc comment 추가. 4. `inject_frontmatter` 의 `head` single binding + CR-only 케이스 추가. 5. `inject_frontmatter` doc 의 yaml_quote escape contract 명시. 테스트 모두 통과 (external 14 unit + ingest_file 4 integration). clippy --workspace clean. 머지 가능.
altair823 added 1 commit 2026-05-07 09:54:14 +00:00
신규 docs/mcp-usage.md (~280 line) — agent integration 의 종합 가이드:

- Quick start + `--config` thread 예시
- Host config 예시 (Claude Code / Cursor / OpenAI Agents / Copilot CLI)
- 6 tool catalog (search / ask / schema / doctor / ingest_file / ingest_stdin)
  각 tool 의 input shape, defaults, output 예시, "언제 사용", mutation
  주의사항.
- Troubleshooting — error.v1 의 7 code 별 조치 표 + grounded:false +
  doctor !ok + empty search + tool-not-found 시나리오.
- Multi-turn ask + session 관리 — session_id 명명, 새 session 시작
  시점, lifetime, single-shot vs session 비교.
- Performance / Security 절.

README.md 의 기존 MCP 절은 quick start 만 유지하고 docs/mcp-usage.md
링크. integrations/claude-code/kebab/SKILL.md 도 동일 cross-link.

agent 사용자 도그푸딩 후속 의견 — host-agnostic 가이드 + 명시적
troubleshooting 표 + multi-turn session 명명 컨벤션 부재 해소.

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

회차 3 — 후속 doc commit (47bfd51) review.

3 file 변경 (+493/-3):

  • 신규 docs/mcp-usage.md (~486 line) — agent integration 종합 가이드.
  • README MCP 절은 quick start 만 유지 + docs/mcp-usage.md cross-link.
  • SKILL.md 도 동일 cross-link 추가.

내용 확인:

  • Quick start + --config thread 예시.
  • Host config 4 가지 (Claude Code / Cursor / OpenAI Agents / Copilot CLI).
  • 6 tool catalog — input shape / defaults / output 예시 / "언제 사용" / mutation 주의사항.
  • Troubleshooting — 7 error.v1 code 별 조치 표 + grounded:false + doctor !ok + empty search + tool-not-found.
  • Multi-turn ask + session 관리 — 명명 컨벤션, 새 session 시점, lifetime, single-shot 비교.
  • Performance / Security 절.

코드 변경 없음 (doc only). 회차 2 APPROVE 의 코드 검증 그대로 유효.

actionable 없음. 머지 가능.

회차 3 — 후속 doc commit (`47bfd51`) review. 3 file 변경 (+493/-3): - 신규 `docs/mcp-usage.md` (~486 line) — agent integration 종합 가이드. - README MCP 절은 quick start 만 유지 + docs/mcp-usage.md cross-link. - SKILL.md 도 동일 cross-link 추가. 내용 확인: - Quick start + `--config` thread 예시. - Host config 4 가지 (Claude Code / Cursor / OpenAI Agents / Copilot CLI). - 6 tool catalog — input shape / defaults / output 예시 / "언제 사용" / mutation 주의사항. - Troubleshooting — 7 error.v1 code 별 조치 표 + grounded:false + doctor !ok + empty search + tool-not-found. - Multi-turn ask + session 관리 — 명명 컨벤션, 새 session 시점, lifetime, single-shot 비교. - Performance / Security 절. 코드 변경 없음 (doc only). 회차 2 APPROVE 의 코드 검증 그대로 유효. actionable 없음. 머지 가능.
altair823 merged commit 4922f9fc64 into main 2026-05-07 09:56:11 +00:00
altair823 deleted branch feat/p9-fb-31-single-file-stdin-ingest 2026-05-07 09:56:13 +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#111