feat(cli): fb-41 PR-4 CLI --multi-hop flag + answer.v1 / error.v1 wire #171
Reference in New Issue
Block a user
Delete Branch "feat/fb-41-pr-4-cli-multi-hop-flag"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
요약
fb-41 multi-hop RAG 의 PR-4 (PR-3b-ii 머지 직후). PR-3b-i / PR-3b-ii 의 multi-hop pipeline 을
kebab ask --multi-hop으로 user-facing CLI 표면에 노출 + answer.v1 / error.v1 JSON Schema 확장.설계: docs/superpowers/specs/2026-05-25-p9-fb-41-multi-hop-rag-design.md
계획: docs/superpowers/plans/2026-05-25-p9-fb-41-multi-hop-rag.md (PR-4 단락)
CLI surface
kebab ask --multi-hop <query>— 새 flag (default false).AskOpts.multi_hop로 전달, stream + non-stream 두 callsite 모두 갱신.--show-citations/--stream/--session등) 와 orthogonal — multi-hop 가 다른 surface 와 자유 조합.--json모드에서 multi-hop happy path / refusal-with-partial-trace 양쪽 경로 모두Answer.hops배열 노출 (PR-3b-i + PR-3b-ii 의 wiring 그대로).Wire schema 확장 (additive)
answer.schema.json:hops: array | null필드 (optional).$defs.HopRecord추가 —iter/kind(decompose|decide|synthesize) /sub_queries/context_chunks_added/forced_stop/llm_call_ms6 필드 + per-field doc.refusal_reason를anyOf [enum, null]로 명시화 — 6 variant (score_gate / llm_self_judge / no_index / no_chunks / llm_stream_aborted / multi_hop_decompose_failed). 이전 schema 의type: string|null보다 strict + 새 variant 정합.error.schema.json:codeenum 에multi_hop_decompose_failed추가. forward-looking — 현재 RefusalReason 은Answer.refusal_reason(stdout) 으로만 노출되고error.v1(stderr) 경로 안 거침. 미래 fatal-promotion 정책 결정 시 reserve.schema_version그대로 (answer.v1/error.v1) — additive minor.Tests (
tests/wire_ask_multi_hop.rs신규, 4 Ollama-free pins)cli_ask_help_advertises_multi_hop_flag—kebab ask --help의 stdout 에--multi-hop등장 (clap-level smoke).answer_schema_declares_hops_property_with_hop_record_defs—hopsproperty +\$defs.HopRecord.kind3 variant 회귀 핀.answer_schema_refusal_reason_enum_includes_multi_hop_decompose_failed— 6 variant 모두 enum 안 (기존 5 도 함께 핀).error_schema_code_enum_includes_multi_hop_decompose_failed— 신규 + 기존 code 보존 핀.End-to-end live Ollama 검증은 후속
#[ignore]test (wire_ask_stale.rs패턴).변경 없음 (의도된 deviation)
kebab-app/src/error_wire.rs— plan 의 "error_wire 매핑" 항목은 현재RefusalReason가Answer.refusal_reason로만 노출 (anyhow chain 안 거침) 라 trigger 가 없음. enum reservation 만으로 충분, 매핑 코드는 dead-code 회피. 향후 fatal-promotion 정책 결정 시 PR-4b 로 split.prompt_template_version(rag-multi-hop-v1) / TUI / MCP — PR-5 / PR-6 의 책임.검증
cargo test -p kebab-cli -j 1— 신규 wire_ask_multi_hop 4 통과 + 기존 ask / search / schema / ingest / mcp / reset 등 모두 통과 (회귀 없음).cargo clippy -p kebab-cli --all-targets -j 1 -- -D warningsclean.시험 항목 (Test Plan)
kebab ask --help의 stdout 에--multi-hop등장answer.schema.json의hopsproperty +\$defs.HopRecord회귀 핀answer.schema.json의refusal_reasonenum 6 variant (multi_hop_decompose_failed + 기존 5)error.schema.json의codeenum 에multi_hop_decompose_failed추가다음 PR
asktoolmulti_hop: boolargument +integrations/claude-code/kebab/SKILL.md의 ask 절 갱신.Assisted-by: Claude Code
fb-41 multi-hop RAG 의 **PR-4** (PR-3b-ii 의 ScriptedLm + tests 위에서 user-facing CLI surface + JSON Schema 확장). PR-3b-i / PR-3b-ii 의 multi-hop pipeline 을 `kebab ask --multi-hop` 으로 사용자에게 노출. 설계: docs/superpowers/specs/2026-05-25-p9-fb-41-multi-hop-rag-design.md 계획: docs/superpowers/plans/2026-05-25-p9-fb-41-multi-hop-rag.md (PR-4 단락) ## CLI surface - `kebab ask --multi-hop <query>` — 새 flag (default false). `AskOpts.multi_hop` 로 전달, stream + non-stream 두 callsite 모두 갱신. - `--show-citations` / `--hide-citations` / `--stream` / `--session` 등 기존 flag 와 orthogonal. - `--json` 모드에서 `Answer.hops` 배열이 multi-hop happy path / refusal-with- partial-trace 양쪽 경로에서 노출됨 (PR-3b-i + PR-3b-ii 의 wiring). ## Wire schema 확장 - `docs/wire-schema/v1/answer.schema.json`: - 신규 `hops: array | null` 필드 (optional, additive). `HopRecord` 의 `$defs` 추가 — `iter` / `kind` (decompose|decide|synthesize) / `sub_queries` / `context_chunks_added` / `forced_stop` / `llm_call_ms` 6 필드 + per-field doc. - `refusal_reason` 필드를 `anyOf [enum, null]` 로 명시 — 6 variant (`score_gate`, `llm_self_judge`, `no_index`, `no_chunks`, `llm_stream_aborted`, `multi_hop_decompose_failed`). 이전 schema 는 `type: string|null` 만 명시 → enum 명시는 agent / consumer 의 strict validate 강화 (additive — 기존 producer 값 모두 enum 안). - `$id` / `schema_version` 변경 없음 — additive minor. - `docs/wire-schema/v1/error.schema.json`: - `code` enum 에 `multi_hop_decompose_failed` 추가. **이는 forward-looking enum extension** — 현재 RefusalReason 은 `Answer.refusal_reason` (stdout) 으로만 노출되고 `error.v1` (stderr) 경로 안 거침. 미래 PR 에서 fatal promotion 정책 결정 시 trigger 가능하도록 enum 만 미리 reserve. - details.description 의 per-code 안내에 `multi_hop_decompose_failed: {}` note 추가 — reserved 상태 명시. ## Tests - `crates/kebab-cli/tests/wire_ask_multi_hop.rs` 신규 (4 Ollama-free pins): - `cli_ask_help_advertises_multi_hop_flag`: clap-level smoke, `kebab ask --help` 출력에 `--multi-hop` 등장 확인. - `answer_schema_declares_hops_property_with_hop_record_defs`: `hops` property 존재 + `$defs.HopRecord` 의 `kind` enum 3 variant (decompose/decide/synthesize) 회귀 핀. - `answer_schema_refusal_reason_enum_includes_multi_hop_decompose_failed`: 6 variant 모두 enum 에 존재 — 기존 5 도 함께 핀 (회귀 방지). - `error_schema_code_enum_includes_multi_hop_decompose_failed`: 신규 code enum 확장 + 기존 code (config_invalid / not_indexed / ...) 보존 핀. End-to-end multi-hop ask 의 live Ollama 검증은 후속 `#[ignore]` test 로 (같은 `wire_ask_stale.rs` 패턴). PR-4 의 범위 = clap + schema 정합성 만. ## 변경 없음 - `crates/kebab-app/src/error_wire.rs` — plan 의 "error_wire 매핑" 항목은 현재 RefusalReason 가 `Answer.refusal_reason` 로만 노출 (anyhow chain 안 거침) 라 trigger 가 없음. enum reservation 만으로 충분, 매핑 코드는 dead code 회피. 향후 fatal-promotion 정책 (refusal → error.v1) 결정 시 PR-4b 로 split. - `prompt_template_version` — `rag-multi-hop-v1` 그대로. - TUI / MCP surface — PR-5 / PR-6 에서. ## 검증 - `cargo test -p kebab-cli -j 1` — 모든 test 통과 (신규 wire_ask_multi_hop 4 + 기존 ask / search / schema / ingest / mcp / reset 등 모두). - `cargo clippy -p kebab-cli --all-targets -j 1 -- -D warnings` clean. - 단일 crate 직렬 build (16 GB RAM 제약). ## 다음 PR - PR-5: MCP `ask` tool 의 `multi_hop: bool` argument + `integrations/claude- code/kebab/SKILL.md` 의 ask 절 갱신. - PR-6: TUI Ask 패널 multi-hop toggle (F2 / Ctrl-T) + hop trace render. - v0.18.0 cut (PR-6 머지 후): `Cargo.toml` 0.17.2 → 0.18.0 + HANDOFF / HOTFIXES / INDEX 갱신 + gitea-release. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>회차 1 — schema description 의 PR 번호 doc 1 건만 정정.
PR-4 의 scope (CLI flag + JSON Schema 확장 + 4 Ollama-free pin) 자체는 컴팩트하고 흐름 깨끗. clap arg + destructure + 2 callsite 의 minimal wiring, additive schema 확장, 4 test 의 회귀 핀 모두 정합. plan 의
error_wire 매핑항목을 dead-code 회피 차원에서 reserve enum 으로 갈음한 deviation 도 commit 본문 + PR body 에 잘 명시됨.본 유일 nit:
answer.schema.json의refusal_reasondescription 이multi_hop_decompose_failed의 도입 시점을 PR-3a 라고 적었지만 실제로는 PR-2 의 변경. inline 코멘트에 정정 제안.@@ -24,0 +35,4 @@},{ "type": "null" }],"description": "p9-fb-41: `multi_hop_decompose_failed` added in PR-3a for the multi-hop pipeline (only emitted when AskOpts.multi_hop = true and the decompose LLM call fails to parse). Other variants are unchanged from earlier phases."doc 부정확: description 의
\multi_hop_decompose_failed` added in PR-3a가 부정확. 실제로는 **PR-2** (#167, commitcf35f36) 에서RefusalReason::MultiHopDecomposeFailedvariant +ask_multi_hop의 decompose-failure 분기를 함께 도입했다. PR-3a (#168) 는Answer.hopsfield +RagCfg` multi-hop knob 만 — refusal_reason variant 와 무관.수정:
added in PR-3a for the multi-hop pipeline→added in PR-2 alongside the multi-hop pipeline skeleton.회차 2 — 회차 1 의 schema description nit (PR-3a → PR-2) 완벽 반영. 추가 actionable 항목 없음 — 머지에 동의.
요약:
--multi-hopflag 가 user-facing surface 에 노출. clap arg + destructure + 2 callsite (stream + non-stream) wiring 깨끗.answer.schema.json의hopsproperty +$defs.HopRecord(6 field, kind enum 3 variant) 추가,refusal_reasonenum 6 variant 명시화 (multi_hop_decompose_failed포함).error.schema.json의codeenum 에multi_hop_decompose_failed추가 (forward-looking reservation, error_wire 매핑은 별 PR-4b 로 split).tests/wire_ask_multi_hop.rs) — clap-help smoke + 3 schema 회귀 핀.schema_version(answer.v1/error.v1) 그대로, 옛 producer / consumer 영향 없음.cargo test -p kebab-cli -j 1모든 test 통과 (회귀 없음),cargo clippy ... -- -D warningsclean.