feat(fb-37): trace + stats — search debug + KB health surface #129

Merged
altair823 merged 13 commits from feat/fb-37-trace-and-stats into main 2026-05-10 07:59:59 +00:00
Owner

Summary

  • search --trace flag emits pre-fusion lex/vec lists + RRF union + per-stage timing on search_response.v1 (additive minor). Cache bypass forced.
  • kebab schema --json extends stats with media_breakdown (5 keys padded), lang_breakdown (NULL keyed "null"), index_bytes (sqlite + lancedb), stale_doc_count (0 when threshold=0). Additive minor.
  • TUI Search pane t key opens TracePopup modal with lex/vec/rrf/timing scrollable.
  • MCP kebab__search accepts trace: bool, mirrors response shape.
  • --trace --mode lexical works without embeddings (NoopRetriever stub).

Design: docs/superpowers/specs/2026-05-10-p9-fb-37-trace-and-stats-design.md
Plan: docs/superpowers/plans/2026-05-10-p9-fb-37-trace-and-stats.md

Test plan

  • cargo test --workspace --no-fail-fast -j 1 green
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • CLI integration: wire_search_trace (3) + wire_schema_breakdowns (2)
  • MCP integration: tools_call_search_trace (3)
  • TUI unit: trace_popup esc + scroll
  • Hybrid retriever search_with_trace lex/vec/rrf/timing
  • Manual smoke: kebab search --trace --json | jq .trace + kebab schema --json | jq .stats
  • Manual TUI smoke: search pane → t opens popup

🤖 Generated with Claude Code

## Summary - search `--trace` flag emits pre-fusion lex/vec lists + RRF union + per-stage timing on `search_response.v1` (additive minor). Cache bypass forced. - `kebab schema --json` extends `stats` with `media_breakdown` (5 keys padded), `lang_breakdown` (NULL keyed `"null"`), `index_bytes` (sqlite + lancedb), `stale_doc_count` (0 when threshold=0). Additive minor. - TUI Search pane `t` key opens `TracePopup` modal with lex/vec/rrf/timing scrollable. - MCP `kebab__search` accepts `trace: bool`, mirrors response shape. - `--trace --mode lexical` works without embeddings (NoopRetriever stub). Design: `docs/superpowers/specs/2026-05-10-p9-fb-37-trace-and-stats-design.md` Plan: `docs/superpowers/plans/2026-05-10-p9-fb-37-trace-and-stats.md` ## Test plan - [x] `cargo test --workspace --no-fail-fast -j 1` green - [x] `cargo clippy --workspace --all-targets -- -D warnings` clean - [x] CLI integration: wire_search_trace (3) + wire_schema_breakdowns (2) - [x] MCP integration: tools_call_search_trace (3) - [x] TUI unit: trace_popup esc + scroll - [x] Hybrid retriever search_with_trace lex/vec/rrf/timing - [ ] Manual smoke: kebab search --trace --json | jq .trace + kebab schema --json | jq .stats - [ ] Manual TUI smoke: search pane → t opens popup 🤖 Generated with [Claude Code](https://claude.com/claude-code)
altair823 added 12 commits 2026-05-10 05:14:52 +00:00
- search --trace boolean flag, additive optional `trace` field on search_response.v1
- HybridRetriever search_with_trace returns (hits, SearchTrace) — lex/vec/rrf_inputs + per-stage timing
- cache bypass when --trace (debug intent)
- schema.v1.stats extended with media_breakdown / lang_breakdown / index_bytes / stale_doc_count
- TUI search pane `t` keystroke opens TracePopup
- additive minor wire — no schema bump

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks: kebab-core types, store breakdowns/index_bytes helpers,
extended CountSummary + Stats wire mirror, HybridRetriever
search_with_trace, App SearchResponse.trace threading, CLI --trace
flag, integration tests, MCP SearchInput.trace, TUI TracePopup,
docs (wire schema + README + SMOKE + INDEX + SKILL).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends CountSummary with media_breakdown, lang_breakdown, stale_doc_count
fields populated via stats_ext::breakdowns(). Adds count_summary_with_threshold
for callers that need real stale counts. Mirrors all new fields onto the
wire-bound Stats struct in kebab-app::schema with #[serde(default)] for
backwards-compat. Also fixes search_budget_integration.rs for the trace field
added to SearchOpts in Task 1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the `trace: Option<SearchTrace>` field to `SearchResponse` and
threads `SearchOpts.trace` through `App::search_with_opts`. When the
caller sets `opts.trace = true` the path bypasses the LRU search cache
and runs through `HybridRetriever::search_with_trace`, which dispatches
all 3 SearchModes internally; this means `--trace` requires embeddings
(same constraint as `--mode hybrid`). The non-trace path keeps its
exact prior behavior with `trace: None` stamped on the response.

Picked up Task 1 / Task 3 follow-ups in the same commit so the
workspace compiles: SearchOpts struct-literals in kebab-cli/main.rs +
kebab-mcp/tools/search.rs default the new `trace` field to false, and
the schema-wrapper test in kebab-cli/wire.rs fills the new
media_breakdown / lang_breakdown / index_bytes / stale_doc_count fields
on Stats with `Default::default()`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also fixes App::search_with_opts trace branch to use NoopRetriever
for SearchMode::Lexical, removing the embeddings requirement when
the user only wants lexical-mode trace.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
altair823 added 1 commit 2026-05-10 07:26:38 +00:00
- doc TraceFusionInput.fusion_score semantics (single-mode vs hybrid)
- comment why total_ms vs stage sum can drift (millis truncation)
- TODO marker on TUI trace popup filter passthrough

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
altair823 merged commit 745a75a82b into main 2026-05-10 07:59:59 +00:00
altair823 deleted branch feat/fb-37-trace-and-stats 2026-05-10 08:00:01 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#129