Skip to content

feat: typed command errors + structured logging - #5

Merged
archae0pteryx merged 3 commits into
mainfrom
feat/typed-errors-logging
May 2, 2026
Merged

feat: typed command errors + structured logging#5
archae0pteryx merged 3 commits into
mainfrom
feat/typed-errors-logging

Conversation

@archae0pteryx

@archae0pteryx archae0pteryx commented May 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • CommandError now derives serde::Serialize with #[serde(tag = "type", content = "message")] — errors cross the Tauri bridge as {type: "not_found", message: "..."} instead of opaque strings
  • tauri-plugin-log wired in — Rust log:: calls land in ~/Library/Logs/adhd-ranch/ (readable in Console.app or via log stream --predicate 'process == "adhd-ranch"')
  • ui_bridge returns Result<T, CommandError> on all commands; mutating ops logged at info, errors at error
  • Frontend: CommandError discriminated union type in src/types/error.ts; mutation APIs log failures via console.error with structured error object

Test plan

  • cargo test --workspace passes (111 tests)
  • tsc --noEmit clean
  • Launch app, create a focus → ~/Library/Logs/adhd-ranch/ has log file with focus created: entry
  • Attempt duplicate focus creation → log shows already_exists error

Summary by CodeRabbit

  • New Features

    • Structured error handling with categorized command errors for clearer UI messages and propagation.
    • App-level logging added to capture runtime events and command results.
  • User-facing Improvements

    • Commands now surface typed errors to the UI and client-side calls log failures for easier troubleshooting.
  • Chores

    • Updated native deps/configuration to enable logging and tray-related features.

CommandError now serializes as {type, message} JSON across the Tauri
bridge — frontend can branch on error kind rather than parsing strings.
tauri-plugin-log wires Rust log:: calls to ~/Library/Logs/adhd-ranch/.

ui_bridge logs mutating ops at info (focus/task/proposal lifecycle) and
all errors at error level. Frontend mutation APIs log failures via
console.error with the typed error object.
@coderabbitai

coderabbitai Bot commented May 2, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ebc13027-7469-480e-a1c4-2fcb00071a5a

📥 Commits

Reviewing files that changed from the base of the PR and between aedb0a6 and 8584c5e.

📒 Files selected for processing (1)
  • src/api/tauriProposalReader.ts

📝 Walkthrough

Walkthrough

Adds structured, serializable command errors and integrates Tauri logging; refactors Tauri command handlers to return CommandError and replaces string-error conversions with logging; updates frontend API wrappers to log and rethrow typed errors.

Changes

Structured Error Handling and Logging Integration

Layer / File(s) Summary
Error Type Definitions
crates/commands/src/error.rs, src/types/error.ts
Rust CommandError now derives serde::Serialize with tagged/renamed fields; TypeScript exports a discriminated CommandError union with variants bad_request, not_found, already_exists, validation, internal, each carrying message: string.
Dependencies / Plugin Initialization
src-tauri/Cargo.toml, src-tauri/src/app/mod.rs
Enabled tauri "tray-icon" feature, added tauri-plugin-log and log deps; initialized tauri_plugin_log::Builder::new().build() in the Tauri Builder plugin chain.
Command Handler Refactor / Logging
src-tauri/src/ui_bridge/mod.rs
Multiple Tauri command handlers (list_focuses, list_proposals, create_focus, delete_focus, append_task, delete_task, accept_proposal, reject_proposal, create_proposal) now return Result<_, CommandError> and use .inspect_err(...) / .inspect(...) for structured logging instead of converting errors to String.
Frontend API Error Wrapping
src/api/focusWriter.ts, src/api/tauriProposalReader.ts
Tauri invoke calls are wrapped with .catch(...) handlers that log the operation and cast the caught value to CommandError before rethrowing; added a local logErr helper in focusWriter.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I tunneled through code tonight,

Typed errors tucked in neat and tight,
Logs lit paths where bugs once played,
Messages clear in brush and glade,
Hop on—errors now behave just right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% 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 'feat: typed command errors + structured logging' accurately and concisely summarizes the main changes: introducing typed CommandError with serde serialization and structured logging via tauri-plugin-log across the codebase.
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.

✏️ 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 feat/typed-errors-logging

Review rate limit: 8/10 reviews remaining, refill in 9 minutes and 8 seconds.

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: 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 `@src-tauri/src/ui_bridge/mod.rs`:
- Line 49: The current inspect_err closure in the create_focus call logs the raw
user-provided title (inspect_err(|e| log::error!("create_focus({title:?}):
{e}"))), which may persist sensitive content; change the inspector to avoid
including the raw title—log only the operation context and error (e.g.,
"create_focus error" plus the error), or if you need reference to the input
include a non-sensitive surrogate such as a fixed "[REDACTED]" tag, a
length/hash indicator, or truncated/normalized form instead of the full title in
the inspect_err closure for create_focus.

In `@src/api/tauriProposalReader.ts`:
- Around line 3-4: Import ordering of the two type imports is incorrect and
fails Biome organizeImports; reorder the type imports so they match the
formatter's expected alphabetical or configured order by swapping the two import
lines referencing the Proposal and CommandError types (types Proposal and
CommandError in tauriProposalReader.ts) so the imports follow the project’s
import sorting rules.
🪄 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 Plus

Run ID: 84ea79fc-49a6-4fa8-9fd2-f8af1c3c725c

📥 Commits

Reviewing files that changed from the base of the PR and between a04868a and aedb0a6.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • crates/commands/src/error.rs
  • src-tauri/Cargo.toml
  • src-tauri/src/app/mod.rs
  • src-tauri/src/ui_bridge/mod.rs
  • src/api/focusWriter.ts
  • src/api/tauriProposalReader.ts
  • src/types/error.ts

})
.map_err(|e| e.to_string())
.inspect(|f| log::info!("focus created: {}", f.id))
.inspect_err(|e| log::error!("create_focus({title:?}): {e}"))

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 | 🟠 Major | ⚡ Quick win

Avoid persisting raw focus titles in error logs.

Line 49 logs user-provided title verbatim into persistent logs, which can capture sensitive personal text. Log operation context and error without raw content.

Proposed diff
-        .inspect_err(|e| log::error!("create_focus({title:?}): {e}"))
+        .inspect_err(|e| log::error!("create_focus failed: {e}"))
📝 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
.inspect_err(|e| log::error!("create_focus({title:?}): {e}"))
.inspect_err(|e| log::error!("create_focus failed: {e}"))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/ui_bridge/mod.rs` at line 49, The current inspect_err closure
in the create_focus call logs the raw user-provided title (inspect_err(|e|
log::error!("create_focus({title:?}): {e}"))), which may persist sensitive
content; change the inspector to avoid including the raw title—log only the
operation context and error (e.g., "create_focus error" plus the error), or if
you need reference to the input include a non-sensitive surrogate such as a
fixed "[REDACTED]" tag, a length/hash indicator, or truncated/normalized form
instead of the full title in the inspect_err closure for create_focus.

Comment thread src/api/tauriProposalReader.ts Outdated
@archae0pteryx
archae0pteryx merged commit 33495d8 into main May 2, 2026
2 checks passed
@archae0pteryx
archae0pteryx deleted the feat/typed-errors-logging branch May 2, 2026 16:18
archae0pteryx added a commit that referenced this pull request May 4, 2026
- Log DisplayConfigState lock failure instead of silently ignoring (#3)
- set_debug_overlay: only emit event when lock succeeds, not on failure (#4)
- SettingsWindow: wrap onToggleDevtools in arrow to explicitly drop the
  boolean arg from ToggleRow onChange (#5)
- Update 032 issue spec to match implemented tray/display behavior (#1)
archae0pteryx added a commit that referenced this pull request May 4, 2026
* [032] Preferences window: settings UI, tray simplification, debug overlay control

- Add on-demand Preferences window (Cmd-,  / tray → Settings…)
  - Sections: General (caps), Widget, Displays, Alerts, Debug
  - Auto-sizes to content via ResizeObserver + Tauri setSize
  - Reopens cleanly after close: destroys stale label, creates fresh window
- Simplify tray: replace Settings submenu with single Settings… item
- Add Tauri commands: get/update settings, get monitors, get/set debug overlay,
  toggle/query devtools
- Debug overlay off by default; toggled via Settings > Debug > Debug Overlay
  using backend app.emit for reliable cross-window event delivery
- DebugOverlayState managed in app; devtools toggle uses is_devtools_open

* fix: address CR comments on 032 preferences window

- Log DisplayConfigState lock failure instead of silently ignoring (#3)
- set_debug_overlay: only emit event when lock succeeds, not on failure (#4)
- SettingsWindow: wrap onToggleDevtools in arrow to explicitly drop the
  boolean arg from ToggleRow onChange (#5)
- Update 032 issue spec to match implemented tray/display behavior (#1)
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