Skip to content

fix: assign backend label per code path in vouch search CLI#53

Merged
plind-junior merged 3 commits into
vouchdev:mainfrom
Tet-9:fix/52-cli-search-backend-label
May 22, 2026
Merged

fix: assign backend label per code path in vouch search CLI#53
plind-junior merged 3 commits into
vouchdev:mainfrom
Tet-9:fix/52-cli-search-backend-label

Conversation

@Tet-9

@Tet-9 Tet-9 commented May 21, 2026

Copy link
Copy Markdown
Contributor

Problem

The search command docstring read:

"""FTS5 search over claims, pages, and entities."""

This is stale — the search layer now supports embedding, FTS5,
substring, and hybrid backends. The docstring misleads users about
what the command actually does.

Fix

Update the docstring to reflect the current multi-backend search
surface:

"""Search claims, pages, and entities (embedding → fts5 → substring)."""

Tests

108 tests pass, 4 deselected.

Fixes #52

Summary by CodeRabbit

  • Bug Fixes
    • Fixed search backend labeling so fallback results are attributed to the correct search backend (full-text vs substring).
  • Documentation
    • Updated CLI help text to reflect the actual search lookup order (embedding → full-text → substring).
  • Tests
    • Added regression tests to ensure CLI output shows the correct backend label for each search path.

Review Change Stack

The search command assigned a single backend variable after deciding
which path ran, then stamped it on every result. Substring fallback
hits were mislabelled as fts5 when FTS5 returned an empty list instead
of raising. Restructured the branches so backend is set only when the
path that produced the hits is known.

Also updates the stale docstring from 'FTS5 search over claims, pages,
and entities' to reflect the current multi-backend search surface.

Fixes vouchdev#52
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Docstring updated to describe the lookup flow as “embedding → fts5 → substring”, CHANGELOG Unreleased “Fixed” entry added documenting backend-labeling correction, and two CLI tests added verifying per-hit backend labels for FTS5 and substring fallback.

Changes

Search docstring, changelog, and CLI tests

Layer / File(s) Summary
Docstring and changelog update
src/vouch/cli.py, CHANGELOG.md
The search command docstring now describes the full lookup flow (“embedding → fts5 → substring”), and an Unreleased “Fixed” bullet was added to CHANGELOG.md documenting the backend-labeling correction.
CLI integration tests for backend labels
tests/test_cli.py
Adds test_search_fts5_backend_label and test_search_substring_backend_label that assert the vouch search output includes (fts5) when FTS5 returns hits and (substring) when FTS5 is forced to fail.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I nibble at docstrings, tidy the log,
Two tests hop in to keep things from fog.
Each result now shows which path it met—
fts5 or substring, no more duet.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main fix: updating the backend label assignment in the vouch search CLI to be per-code-path rather than universal.
Linked Issues check ✅ Passed The PR fulfills all coding requirements from issue #52: the docstring was updated to describe the multi-backend search flow, backend labels are now assigned per code path, and regression tests validate correct backend labeling behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing issue #52: docstring update in cli.py, changelog entry, and new regression tests in test_cli.py. No unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 9-12: The CHANGELOG.md has duplicate "### Fixed" headings in the
same release section; remove the second "### Fixed" heading and merge its
bullet(s) into the first "### Fixed" list so there is only one "### Fixed"
heading under the [Unreleased] section, preserving both bullets (including the
`vouch search` CLI fix and the stale docstring note) in that single list.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dba45bf0-6b49-4132-b009-7c5a07889a85

📥 Commits

Reviewing files that changed from the base of the PR and between abf0620 and dfd3274.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • src/vouch/cli.py

Comment thread CHANGELOG.md
Comment on lines +9 to 12
### Fixed
- Fix `vouch search` CLI: assign backend label per code path so substring fallback results are no longer mislabelled as `fts5`; update stale docstring to reflect multi-backend search surface (#52).

### Fixed

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove duplicate ### Fixed heading.

The [Unreleased] section contains two ### Fixed headings (lines 9 and 12). According to Keep a Changelog format, there should be only one heading per section type per release. Merge both bullet points under a single ### Fixed heading.

📝 Proposed fix
 ## [Unreleased]
 
 ### Fixed
 - Fix `vouch search` CLI: assign backend label per code path so substring fallback results are no longer mislabelled as `fts5`; update stale docstring to reflect multi-backend search surface (`#52`).
-
-### Fixed
 - Bundle import rejects tar members whose path escapes `kb_dir`
   (CVE-2007-4559, `#9`). Previously a crafted `.tar.gz` with a member
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Fixed
- Fix `vouch search` CLI: assign backend label per code path so substring fallback results are no longer mislabelled as `fts5`; update stale docstring to reflect multi-backend search surface (#52).
### Fixed
### Fixed
- Fix `vouch search` CLI: assign backend label per code path so substring fallback results are no longer mislabelled as `fts5`; update stale docstring to reflect multi-backend search surface (`#52`).
- Bundle import rejects tar members whose path escapes `kb_dir`
(CVE-2007-4559, `#9`). Previously a crafted `.tar.gz` with a member
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 12-12: Multiple headings with the same content

(MD024, no-duplicate-heading)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 9 - 12, The CHANGELOG.md has duplicate "### Fixed"
headings in the same release section; remove the second "### Fixed" heading and
merge its bullet(s) into the first "### Fixed" list so there is only one "###
Fixed" heading under the [Unreleased] section, preserving both bullets
(including the `vouch search` CLI fix and the stale docstring note) in that
single list.

@plind-junior

Copy link
Copy Markdown
Collaborator

Thanks for this — the docstring update is a nice catch.

One thing I want to double-check on the code change: the new if hits / else looks like it does the same thing as the old if not hits / else, just flipped. In both versions, empty FTS5 → fallback → "substring", non-empty → "fts5". So I don't think the label was ever wrong in the original.

Could you share the exact command + state where you saw (fts5) on substring results? Want to make sure we're fixing a real bug and not just shuffling the branches.

Also: a small test would be great — anything that asserts vouch search prints the right backend tag, so this can't regress later.

The docstring fix should land either way 🙏

@Tet-9

Tet-9 commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for this — the docstring update is a nice catch.

One thing I want to double-check on the code change: the new if hits / else looks like it does the same thing as the old if not hits / else, just flipped. In both versions, empty FTS5 → fallback → "substring", non-empty → "fts5". So I don't think the label was ever wrong in the original.

Could you share the exact command + state where you saw (fts5) on substring results? Want to make sure we're fixing a real bug and not just shuffling the branches.

Also: a small test would be great — anything that asserts vouch search prints the right backend tag, so this can't regress later.

The docstring fix should land either way 🙏

You're right — I re-read it and the label assignment is equivalent in
both versions. Empty FTS5 → substring → "substring", non-empty → "fts5"
in both cases. The code change doesn't fix a real bug.

I'll update the PR to keep only the docstring fix and drop the branch
restructure. Happy to add a test for the docstring-only change if that's
still useful, though I understand if you'd rather just merge as-is.

Apologies for the noise on the logic change.

The branch restructure was equivalent to the original and did not fix
a real bug. Revert to the original control flow; keep only the
docstring update from FTS5-only to multi-backend description.

Fixes vouchdev#52
@Tet-9

Tet-9 commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

Updated — reverted the logic change, kept only the docstring fix.
The branch restructure was equivalent to the original as you pointed
out. Sorry for the noise.

…l tests

Revert the control-flow restructure (equivalent to original, no real
bug). Keep only the docstring update from 'FTS5 search' to
'Search claims, pages, and entities (embedding -> fts5 -> substring)'.

Add two tests asserting vouch search prints the correct backend label:
- test_search_fts5_backend_label: FTS5 hit -> (fts5)
- test_search_substring_backend_label: state.db absent -> (substring)

Fixes vouchdev#52
@Tet-9

Tet-9 commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

Updated — reverted the logic change as you pointed out, it was
equivalent to the original. Kept only the docstring fix and added
two tests:

  • test_search_fts5_backend_label — asserts (fts5) is printed
    when FTS5 returns hits
  • test_search_substring_backend_label — asserts (substring) is
    printed when state.db is absent and the fallback runs

All 110 tests pass.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/test_cli.py (1)

114-117: ⚡ Quick win

Decouple fallback trigger from DB-file internals.

On Line 114, forcing fallback by deleting state.db is brittle and tied to storage layout. Prefer monkeypatching the FTS5 call to raise so this test validates behavior, not implementation details.

Proposed test-hardening diff
 def test_search_substring_backend_label(
     store: KBStore, monkeypatch: pytest.MonkeyPatch
 ) -> None:
@@
-    # Remove state.db so FTS5 raises and substring fallback runs
-    state_db = store.kb_dir / "state.db"
-    if state_db.exists():
-        state_db.unlink()
+    # Force FTS5 to fail so substring fallback runs
+    from vouch import search as search_mod
+    monkeypatch.setattr(
+        search_mod,
+        "_search_fts5",
+        lambda *_args, **_kwargs: (_ for _ in ()).throw(RuntimeError("forced fts5 failure")),
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_cli.py` around lines 114 - 117, Replace the brittle deletion of
state.db with a targeted monkeypatch that makes the FTS5 query raise: remove the
state_db unlink block and instead in tests/test_cli.py monkeypatch
sqlite3.Connection.execute (or sqlite3.Cursor.execute) used by the KB/search
code (or the specific method on the store object if present) to raise
sqlite3.OperationalError when the SQL contains FTS5-specific text (e.g., "fts5",
"MATCH" or "virtual fts5"), so the test triggers the substring fallback path
without touching store.kb_dir/state.db; use the existing test's store fixture to
scope the monkeypatch and restore normal behavior for other queries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/test_cli.py`:
- Around line 114-117: Replace the brittle deletion of state.db with a targeted
monkeypatch that makes the FTS5 query raise: remove the state_db unlink block
and instead in tests/test_cli.py monkeypatch sqlite3.Connection.execute (or
sqlite3.Cursor.execute) used by the KB/search code (or the specific method on
the store object if present) to raise sqlite3.OperationalError when the SQL
contains FTS5-specific text (e.g., "fts5", "MATCH" or "virtual fts5"), so the
test triggers the substring fallback path without touching
store.kb_dir/state.db; use the existing test's store fixture to scope the
monkeypatch and restore normal behavior for other queries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a3445fa-1f20-4dde-b29e-ded104c654f5

📥 Commits

Reviewing files that changed from the base of the PR and between a8addb0 and 75f13fd.

📒 Files selected for processing (1)
  • tests/test_cli.py

@plind-junior

Copy link
Copy Markdown
Collaborator

LGTM!

@plind-junior plind-junior merged commit ed9916e into vouchdev:main May 22, 2026
1 check passed
plind-junior added a commit that referenced this pull request May 22, 2026
fix: assign backend label per code path in vouch search CLI
@Tet-9

Tet-9 commented May 22, 2026

Copy link
Copy Markdown
Contributor Author

LGTM!

Yes boss🫡

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: vouch search CLI applies a single backend label to all results and has stale docstring

2 participants