fix(cli): honor --config flag in kb ask (P4-3 follow-up)

The earlier P3-5 hotfix wired --config through ingest / search / list /
inspect / doctor by switching kb-cli to call the *_with_config
companions. P4-3 added the ask body but kb-cli's Cmd::Ask arm still
called bare kb_app::ask(query, opts) — same bug as before, ask
silently fell back to ~/.config/kb/config.toml regardless of what the
user passed.

Caught during the post-P4-3 smoke against /tmp/kb-smoke/ pointed at
192.168.0.47 Ollama with gemma4:26b: the answer's wire JSON reported
`model.id = "qwen2.5:14b-instruct"` (the user's XDG default) instead
of `gemma4:26b` from the explicit --config, plus the score_gate /
data_dir / model fields all reflected XDG defaults. After this fix
the same invocation correctly returns model.id=gemma4:26b,
embedding=multilingual-e5-small (from the smoke config), grounded=true
with `[#2]` citation pointing at rust/ownership.md.

Same minimal pattern as the P3-5 hotfix:
- Build the Config once via Config::load(cli.config.as_deref()).
- Call kb_app::ask_with_config(cfg, query, opts) instead of
  kb_app::ask(query, opts).

Workspace 319 tests pass; cargo clippy --workspace --all-targets --
-D warnings clean.

Smoke verified across four scenarios:
- Korean→Korean-body lookup: grounded with rust/ownership.md citation.
- English→Korean-body cross-language: grounded with arch/rag-
  architecture.md citation.
- Korean→English-body cross-language: grounded with arch/embeddings.md
  citation.
- Out-of-corpus query: LlmSelfJudge refusal with "근거가 부족하다."

Out of scope (filed for follow-up):
- config.rag.score_gate default 0.05 is incompatible with hybrid
  RRF scores. RRF top score is bounded by 2/k_rrf (≈0.033 at k_rrf
  =60), so the spec default trips ScoreGate on every hybrid query.
  Workaround: lower the gate to 0.005 in the user's config; long-
  term fix needs either per-mode gate config or RRF score
  normalization to [0,1]. Tracked separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 15:56:57 +00:00
parent 6210c52efd
commit ed8bf87c65

View File

@@ -320,6 +320,7 @@ fn run(cli: &Cli) -> anyhow::Result<()> {
temperature,
seed,
} => {
let cfg = kb_config::Config::load(cli.config.as_deref())?;
let opts = kb_app::AskOpts {
k: *k,
explain: *explain,
@@ -331,7 +332,7 @@ fn run(cli: &Cli) -> anyhow::Result<()> {
// wires up a real `mpsc::Sender` here.
stream_sink: None,
};
let ans = kb_app::ask(query, opts)?;
let ans = kb_app::ask_with_config(cfg, query, opts)?;
if cli.json {
println!("{}", serde_json::to_string(&wire::wire_answer(&ans))?);
} else {