Skip to content

fix: search ranking, layout gaps, content truncation in BrainBar#133

Merged
EtanHey merged 2 commits intomainfrom
fix/brainbar-formatting-iteration
Mar 29, 2026
Merged

fix: search ranking, layout gaps, content truncation in BrainBar#133
EtanHey merged 2 commits intomainfrom
fix/brainbar-formatting-iteration

Conversation

@EtanHey
Copy link
Copy Markdown
Owner

@EtanHey EtanHey commented Mar 29, 2026

Summary

Follow-up to #132. Fixes 4 issues found during live testing:

  • FTS5 ranking: ORDER BY c.rowid ASCORDER BY f.rank (BM25 relevance). Results now sorted by actual match quality instead of insertion order.
  • Score zero: Added f.rank to SELECT, exposed as positive score field. Scores were always 0.00 before.
  • Layout gap: Removed trailing empty line after last search result. └─ now follows directly.
  • Content truncation: Increased summary display from 72 → 150 chars so results are actually readable.

Files Changed

File What
BrainDatabase.swift Add f.rank to SELECT, ORDER BY f.rank, expose score
Formatters.swift Remove trailing , increase maxLen to 150
DatabaseTests.swift +2 tests: non-zero score, relevance ordering
FormattersTests.swift +3 tests: no trailing gap (single/multi), truncation at 150

Test plan

  • 67/67 tests green (5 new)
  • Live socat test: scores 28.00, 26.87, 26.28 for "overnight hardening sprint"
  • No trailing gap before └─
  • Content shows 150 chars instead of 72

🤖 Generated with Claude Code

Note

Fix search ranking, layout gaps, and content truncation in BrainBar

  • Changes search result ordering in BrainDatabase.search to use FTS5 BM25 relevance (f.rank) instead of rowid for non-unread searches; each result now includes a positive score field derived from the rank.
  • Increases content truncation length in Formatters.formatSearchResults from 72 to 150 characters and removes the trailing separator line after the last result.
  • Adds tests covering score presence, relevance ordering, truncation length, and absence of trailing separator gaps.

Macroscope summarized 805af1b.

Summary by CodeRabbit

  • New Features

    • Search results now include a relevance score and are ordered by relevance.
  • Bug Fixes

    • Search result summaries now show up to 150 characters.
    • Removed extra trailing separator so lists no longer end with an extra divider.
  • Tests

    • Added tests validating relevance scoring, result ordering, truncation, and formatting.

…formatters

1. FTS5 ranking: Add f.rank to search query, ORDER BY f.rank instead of
   c.rowid ASC. Results now sorted by BM25 relevance score. Score exposed
   as positive number in results (negated from FTS5's negative convention).

2. Layout: Remove trailing empty │ line after last search result. The └─
   closer now follows directly after the last result's tags/content line.
   Separator │ lines still appear between results, just not after the last.

3. Content truncation: Increase summary/snippet display from 72 to 150
   chars so results are actually readable in the terminal.

67/67 tests green (5 new: 2 layout, 1 truncation, 2 ranking).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented Mar 29, 2026

@coderabbitai review

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented Mar 29, 2026

@greptileai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 29, 2026

📝 Walkthrough
📝 Walkthrough
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: fixing FTS5 search ranking, removing layout gaps, and adjusting content truncation in BrainBar.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/brainbar-formatting-iteration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented Mar 29, 2026

@codex review

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented Mar 29, 2026

@cursor @BugBot review

@cursor
Copy link
Copy Markdown

cursor Bot commented Mar 29, 2026

Good! The search results are only consumed by Formatters.formatSearchResults(), which already expects and uses the score field. This is safe.

Status: ✅ No backward compatibility issues

Summary of Bug Review

APPROVED - No Critical Bugs Found

Issues Found:

  1. ⚠️ Minor Risk: Test testSearchResultsOrderedByRelevance() could be brittle if FTS5's BM25 scoring changes behavior, but should be stable in practice given the test data (2 term occurrences vs 1).

Verified Correct:

  1. ✅ Column indexing is correct (f.rank at index 10)
  2. ✅ FTS5 rank ordering is correct (ascending gives best matches first)
  3. ✅ Score calculation correctly negates FTS5's negative rank
  4. ✅ Loop condition correctly excludes trailing separator
  5. ✅ Edge cases (empty results, zero score, missing summary) handled correctly
  6. ✅ No backward compatibility issues (score field is new, only consumed by formatter)
  7. ✅ All 5 new tests properly validate the changes

Code Quality:

  • Clear, well-documented changes
  • Comprehensive test coverage (67/67 tests passing)
  • Proper handling of edge cases
  • No SQL injection risks
  • No performance regressions

Recommendations:

  1. Optional Enhancement: Consider adding a test that verifies the score is monotonically decreasing (each result has score ≤ previous result) to catch any future ordering regressions more reliably.

  2. Documentation: The PR description and commit message are excellent and clearly explain the changes.

The code changes are solid and well-tested. This is a clean bug fix PR with good test coverage.

Open in Web Open in Cursor 

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@brain-bar/Sources/BrainBar/BrainDatabase.swift`:
- Line 237: The change to ORDER BY f.rank breaks unread delivery watermark
semantics because the code still advances the unread watermark using maxRowID
from the returned page; when unreadOnly is true and limit is applied this can
mark unseen rows as delivered. Modify the logic that advances the
delivery/unread watermark (the code using maxRowID in the unreadOnly path) so
that when unreadOnly is true you either (a) compute the watermark from the
contiguous highest row_id sequence (sorting the returned rows by row_id and
taking the largest contiguous row_id) rather than the max row_id of the
f.rank-ordered page, or (b) force the query/ordering to preserve row_id
contiguity for watermark calculation; ensure references to f.rank remain for
relevance sorting but do not use that ordering to compute the unread watermark
in advanceUnread/unread delivery code paths.

In `@brain-bar/Tests/BrainBarTests/FormattersTests.swift`:
- Around line 327-340: The test testSearchResultsSummaryTruncatesAt150 only
checks that the full 200-char input isn't present; update it to assert the exact
truncation behavior by locating the test function and the variables longSummary,
out, and contentLine, then extract the displayed summary from contentLine and
assert it equals the expected 150-character truncated string (149 "x" characters
plus the ellipsis character) or otherwise assert the displayed summary length is
150 and ends with the ellipsis; this ensures Formatters.formatSearchResults
actually truncates to 150 chars.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 56589442-8683-4cc8-a788-1bbf50b138cb

📥 Commits

Reviewing files that changed from the base of the PR and between 261c9a0 and 27b6830.

📒 Files selected for processing (4)
  • brain-bar/Sources/BrainBar/BrainDatabase.swift
  • brain-bar/Sources/BrainBar/Formatters.swift
  • brain-bar/Tests/BrainBarTests/DatabaseTests.swift
  • brain-bar/Tests/BrainBarTests/FormattersTests.swift
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-03-18T00:12:08.774Z
Learnt from: EtanHey
Repo: EtanHey/brainlayer PR: 87
File: brain-bar/Sources/BrainBar/BrainBarServer.swift:118-129
Timestamp: 2026-03-18T00:12:08.774Z
Learning: In Swift files under brain-bar/Sources/BrainBar, enforce that when a critical dependency like the database is nil due to startup ordering (socket before DB), any tool handler that accesses the database must throw an explicit error (e.g., ToolError.noDatabase) instead of returning a default/empty value. Do not allow silent defaults (e.g., guard let db else { return ... }). Flag patterns that silently return defaults when db is nil, as this masks startup timing issues. This guidance applies broadly to similar Swift files in the BrainBar module, not just this one location.

Applied to files:

  • brain-bar/Sources/BrainBar/Formatters.swift
  • brain-bar/Sources/BrainBar/BrainDatabase.swift
🔇 Additional comments (3)
brain-bar/Sources/BrainBar/Formatters.swift (1)

111-111: Formatting updates look correct and aligned with expected UX.

The 150-char truncation and “no trailing separator after last result” logic are clean and match the intended output behavior.

Also applies to: 132-135

brain-bar/Tests/BrainBarTests/FormattersTests.swift (1)

300-323: Good coverage for trailing separator regression.

These tests correctly guard against the extra trailing line in both single and multi-result outputs.

brain-bar/Tests/BrainBarTests/DatabaseTests.swift (1)

318-337: Nice additions for ranking regression protection.

These tests provide useful guardrails for both score population and relevance ordering behavior.

Comment thread brain-bar/Sources/BrainBar/BrainDatabase.swift Outdated
Comment thread brain-bar/Tests/BrainBarTests/FormattersTests.swift
…n test

Address CodeRabbit review findings:

1. CRITICAL: ORDER BY f.rank broke unread delivery watermark. When
   unreadOnly=true, maxRowID from rank-sorted results could skip rowids
   and mark unseen chunks as delivered. Fix: use rowid ASC for unread
   queries, f.rank for normal search.

2. MAJOR: Truncation test was weak — only checked 200-char string absent.
   Now asserts exact 149 chars + ellipsis (150 total) is present.

67/67 tests green.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented Mar 29, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 27b6830301

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

JOIN chunks c ON c.id = f.chunk_id
WHERE \(conditions.joined(separator: " AND "))
ORDER BY c.rowid ASC
ORDER BY f.rank
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep unread search ordered by rowid

Ordering all searches by f.rank breaks the delivery watermark logic when unreadOnly is used: this function still updates last_delivered_seq from maxRowID after a limited fetch, but relevance ordering is not monotonic by rowid. In a batch where a high-rowid item ranks highly, markDelivered can advance past older unread rows that were never returned, causing later unread/ack flows to skip those memories. Preserve rowid-ordered paging for unread mode (or only advance through contiguous rowids) so unread items are not dropped.

Useful? React with 👍 / 👎.

@EtanHey EtanHey merged commit eff4ad0 into main Mar 29, 2026
1 of 5 checks passed
@EtanHey EtanHey deleted the fix/brainbar-formatting-iteration branch March 29, 2026 18:47
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.

1 participant