Skip to content

Fix BrainBar UI stats DB read-only mode#300

Merged
EtanHey merged 1 commit into
fix/brainbar-hybrid-parityfrom
fix/brainbar-ui-readonly-stats
May 18, 2026
Merged

Fix BrainBar UI stats DB read-only mode#300
EtanHey merged 1 commit into
fix/brainbar-hybrid-parityfrom
fix/brainbar-ui-readonly-stats

Conversation

@EtanHey
Copy link
Copy Markdown
Owner

@EtanHey EtanHey commented May 18, 2026

Summary

  • Open the BrainBar UI stats database connection with SQLite READONLY flags and PRAGMA query_only = ON.
  • Keep the daemon/server path as the sole read-write owner while preserving dashboard stats reads.
  • Add regression coverage proving read-only dashboard stats can read existing rows and reject writes.

Test plan

  • swift test --package-path brain-bar --filter DatabaseTests/testReadOnlyOpenConfigurationAllowsDashboardReadsButRejectsWrites
  • pytest tests/test_brainbar_build_app_guards.py -q
  • Live daemon/UI smoke: daemon opens temp DB READWRITE, UI opens same DB READONLY, killing UI leaves daemon MCP initialize healthy
  • swift test --package-path brain-bar
  • push hook: pytest unit suite, MCP registration, eval/hook routing, bun stale-index test, FTS5 regression shell

Note

Medium Risk
Changes SQLite connection flags/PRAGMAs and schema-migration behavior, which could affect DB availability/locking if misconfigured, but is scoped to the UI stats reader path and covered by new tests.

Overview
Makes the BrainBar UI dashboard stats DB connection read-only so the daemon remains the sole read-write owner.

Adds readOnly to BrainDatabase.OpenConfiguration, opening connections with SQLITE_OPEN_READONLY + PRAGMA query_only=ON, and skipping migration/schema checks and write-oriented PRAGMAs when in read-only mode.

Threads the configuration through StatsCollector/makeStatsCollector, sets makeUIStatsCollector to readOnly: true, adds reopenIfNeeded() to self-heal when the DB appears later, and adds regression tests verifying read-only reads succeed, writes fail, and the collector can reopen after the daemon creates the DB.

Reviewed by Cursor Bugbot for commit 8a05bc0. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix BrainBar UI stats collector to open the database in read-only mode

  • Adds readOnly support to BrainDatabase.OpenConfiguration, which sets SQLite query_only mode, adjusts cache size, and skips schema/migration checks on open.
  • Updates BrainBarAppSupport.makeUIStatsCollector to pass OpenConfiguration(readOnly: true) so the UI process never attempts writes to the stats DB.
  • Adds BrainDatabase.reopenIfNeeded() and calls it in StatsCollector.refresh so stats load once the DB becomes available after the daemon creates it.
  • Adds tests covering read-only dashboard reads, write rejection, and deferred DB availability scenarios.

Macroscope summarized 8a05bc0.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added read-only database access mode to enhance safety and prevent accidental data modifications
    • Dashboard statistics collector now uses read-only database configuration by default
  • Improvements

    • Enhanced database configuration flexibility with parameterized open settings
  • Tests

    • Added test coverage for read-only database operations and access patterns

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

The PR extends BrainDatabase.OpenConfiguration to support read-only mode and threads this configuration through StatsCollector initialization. App helpers now explicitly wire read-only configuration for UI stats collection, while the core database layer applies SQLite read-only flags and pragmas during connection setup.

Changes

Read-only Database Configuration

Layer / File(s) Summary
Read-only database configuration contract
brain-bar/Sources/BrainBar/BrainDatabase.swift
OpenConfiguration stores readOnly: Bool flag. openAndConfigure() skips schema migration when read-only and returns early. openConnection and configureConnection apply SQLite read-only flags (SQLITE_OPEN_READONLY) and pragmas (query_only=ON) when enabled.
StatsCollector database configuration parameter
brain-bar/Sources/BrainBar/Dashboard/StatsCollector.swift
StatsCollector initializer accepts databaseOpenConfiguration parameter and passes it to BrainDatabase constructor.
App helper read-only wiring
brain-bar/Sources/BrainBar/BrainBarApp.swift
makeStatsCollector accepts databaseOpenConfiguration parameter and threads it to StatsCollector. makeUIStatsCollector explicitly passes BrainDatabase.OpenConfiguration(readOnly: true) when creating UI stats.
Read-only mode validation test
brain-bar/Tests/BrainBarTests/DatabaseTests.swift
New test testReadOnlyOpenConfigurationAllowsDashboardReadsButRejectsWrites verifies that a read-only database instance can read dashboard stats but throws when attempting write operations.

Possibly related PRs

  • EtanHey/brainlayer#273: Modifies BrainDatabase.OpenConfiguration initialization and wiring (adds configurable options like busyTimeoutMillis and open error tracking).
  • EtanHey/brainlayer#136: Introduces the dashboard StatsCollector feature that this PR extends with read-only configuration support.
  • EtanHey/brainlayer#145: Modifies StatsCollector.init(...) signature (removes observer wiring), which may conflict with this PR's databaseOpenConfiguration parameter addition.

Poem

🐰 Read-only reads are now blessed,
With pragmas set and flags compressed,
StatsCollector knows the way,
Through BrainDatabase's careful ballet—
No writes allowed on this fine day!


🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Title check ✅ Passed The title 'Fix BrainBar UI stats DB read-only mode' directly and clearly describes the main change across all modified files: adding read-only database mode support to the BrainBar UI's stats collector.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
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-ui-readonly-stats

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 May 18, 2026

@cursor @BugBot review

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented May 18, 2026

@codex review

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented May 18, 2026

@coderabbitai review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 18, 2026

You need to increase your spend limit or enable usage-based billing to run background agents. Go to Cursor

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 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: 29b74be701

ℹ️ 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".

targetPID: 0,
brainBusEvents: brainBusEvents
brainBusEvents: brainBusEvents,
databaseOpenConfiguration: BrainDatabase.OpenConfiguration(readOnly: true)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reopen the UI stats DB after read-only startup misses

When the menu UI starts against a fresh install or a new BRAINBAR_DB_PATH before the daemon has created brainlayer.db, this read-only open cannot create the database, so BrainDatabase is left with no handle. StatsCollector.refresh() only catches notOpen and never retries openAndConfigure, so even after the daemon later creates the DB and emits bus events, the dashboard remains permanently degraded until the app is restarted. Either delay this read-only collector until the daemon DB exists or add a reopen path on refresh/events.

Useful? React with 👍 / 👎.

@EtanHey EtanHey force-pushed the fix/brainbar-ui-readonly-stats branch from 29b74be to 8a05bc0 Compare May 18, 2026 10:51
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 May 18, 2026

@codex review

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented May 18, 2026

@coderabbitai review

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented May 18, 2026

@cursor @BugBot re-review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 18, 2026

You need to increase your spend limit or enable usage-based billing to run background agents. Go to Cursor

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 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.

@EtanHey
Copy link
Copy Markdown
Owner Author

EtanHey commented May 18, 2026

Codex P2 follow-up fixed in 8a05bc0: added DashboardTests/testReadOnlyStatsCollectorReopensAfterDaemonCreatesDatabase for UI startup before daemon DB creation, added BrainDatabase.reopenIfNeeded(), reset partial DB handles/isOpen on failure/close, and call reopen before stats refresh reads. Verification: focused regression passed, full swift test --package-path brain-bar passed 369 tests, and push gate passed: Python 2020 passed/9 skipped/75 deselected/1 xfailed, MCP 3, eval/hook 32, Bun 1, FTS5 regression.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ 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".

@EtanHey EtanHey merged commit 931fa93 into fix/brainbar-hybrid-parity May 18, 2026
3 checks passed
@EtanHey EtanHey deleted the fix/brainbar-ui-readonly-stats branch May 18, 2026 11:04
EtanHey added a commit that referenced this pull request May 18, 2026
* fix: route BrainBar search through Python hybrid helper

* fix: harden BrainBar hybrid helper startup

* fix: address BrainBar hybrid review followups

* fix: report hybrid helper launch failures

* fix: keep source all unfiltered for entity routing

* fix: bound hybrid helper socket waits

* fix: harden hybrid helper fallback cleanup

* fix: sanitize hybrid helper responses

* feat: stream BrainBar brain bus events

* refactor: use NSStatusItem popover shell

* fix: prevent SIGPIPE from hybrid helper socket writes

* fix: route BrainBar search through Python hybrid helper

* fix: harden BrainBar hybrid helper startup

* fix: address BrainBar hybrid review followups

* fix: report hybrid helper launch failures

* fix: keep source all unfiltered for entity routing

* fix: bound hybrid helper socket waits

* fix: harden hybrid helper fallback cleanup

* fix: sanitize hybrid helper responses

* feat: stream BrainBar brain bus events

* refactor: use NSStatusItem popover shell

* fix: prevent SIGPIPE from hybrid helper socket writes

* fix: serialize BrainBus socket writes

* refactor: split BrainBar daemon and UI (#298)

* fix: refresh BrainBar stats before bus events

* test: wait for BrainBar socket readiness

* test: relax arbitration drain deadline

* fix: open BrainBar UI stats database read-only (#300)
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