Skip to content

Conversation

Brendonovich
Copy link
Member

@Brendonovich Brendonovich commented Oct 2, 2025

We've been getting error reports from some Windows devices about an interface not being marshalled on the right thread, it seems to be coming from stopping the recording. I've moved the direct3d capturer onto a dedicated thread just in case.

Summary by CodeRabbit

  • New Features

    • Enabled system audio capture in the recording CLI example.
  • Refactor

    • Reworked Windows screen capture start/stop to use a dedicated thread with coordinated stopping for improved responsiveness and cleaner shutdown.
    • Standardized stop error reporting to provide simpler, clearer feedback when capture stops fail.
  • Chores

    • CI now runs Clippy linting to improve code quality.

Copy link
Contributor

coderabbitai bot commented Oct 2, 2025

Walkthrough

Enables system audio in the recording CLI example. Refactors Windows screen capture to run in a dedicated thread with readiness and stop coordination via channels, replaces the in-process capturer handle, and changes StopCapturing reply type to String. CI setup adds the Clippy component.

Changes

Cohort / File(s) Summary
Recording CLI example
crates/recording/examples/recording-cli.rs
Enables system audio by activating .with_system_audio(true) in the Actor builder chain.
Windows screen capture orchestration
crates/recording/src/sources/screen_capture/windows.rs
Replaces in-process capture_handle with a stop_tx channel (SyncSender<oneshot::Sender<Result<(), StopCapturerError>>>); spawns a thread for capturer lifecycle; adds oneshot readiness and stop signaling; maps stop errors to String; updates imports to include futures::channel::oneshot and scap_direct3d::StopCapturerError.
CI: Rust tooling
.github/workflows/ci.yml
Adds components: clippy to the Rust toolchain setup step so CI installs Clippy.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant ScreenCaptureActor as ScreenCaptureActor
  participant CapturerThread as "Capturer Thread"
  participant Capturer

  Caller->>ScreenCaptureActor: StartCapturing
  activate ScreenCaptureActor
  ScreenCaptureActor->>CapturerThread: spawn thread (ready oneshot + stop mpsc)
  activate CapturerThread
  CapturerThread->>Capturer: initialize/start capturer
  CapturerThread-->>ScreenCaptureActor: send ready via oneshot
  note right of Capturer: capture loop runs, frames -> handlers
  deactivate ScreenCaptureActor

  Caller->>ScreenCaptureActor: StopCapturing
  activate ScreenCaptureActor
  ScreenCaptureActor->>CapturerThread: send oneshot Sender over stop mpsc
  CapturerThread->>Capturer: stop()
  CapturerThread-->>ScreenCaptureActor: send stop result (Result<(), StopCapturerError>)
  ScreenCaptureActor-->>Caller: Reply mapped to Result<(), String>
  deactivate ScreenCaptureActor
  deactivate CapturerThread
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

I tuned my ears to system song,
A thread now hums and runs along.
Oneshoot ready, one to cease,
I hop, I build, then rest in peace.
Clippy winks — the CI's bright tonight. 🥕✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title directly reflects the core change of moving the Windows capturer onto a dedicated thread to address marshalling issues, matching the code modifications and PR objectives in a concise and clear way without unnecessary detail.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch single-thread-windows-capture

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a09ae2 and dbb8f7b.

📒 Files selected for processing (1)
  • crates/recording/src/sources/screen_capture/windows.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
🧬 Code graph analysis (1)
crates/recording/src/sources/screen_capture/windows.rs (3)
crates/recording/src/feeds/camera.rs (11)
  • oneshot (336-336)
  • handle (326-400)
  • handle (406-422)
  • handle (428-430)
  • handle (436-453)
  • handle (459-465)
  • handle (471-487)
  • handle (503-539)
  • handle (545-569)
  • handle (575-591)
  • handle (597-610)
crates/scap-direct3d/src/lib.rs (4)
  • new (140-335)
  • d3d_device (193-193)
  • d3d_device (345-347)
  • d3d_device (458-460)
crates/mediafoundation-utils/src/lib.rs (1)
  • thread_init (18-21)
⏰ 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). (4)
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Analyze (rust)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
crates/recording/src/sources/screen_capture/windows.rs (4)

9-11: LGTM: Imports support thread coordination.

The oneshot and StopCapturerError imports are correctly added to support the new thread-based capturer lifecycle with readiness and stop coordination channels.


373-381: LGTM: Field correctly replaces in-process capturer with stop channel.

The stop_tx field properly replaces the in-process capture_handle with a coordination channel to the spawned thread. The Option wrapper correctly represents "not capturing" state, and initialization to None is appropriate.


429-498: LGTM: Thread-based capturer with proper coordination.

The refactored StartCapturing correctly:

  • Spawns a dedicated thread with COM/MF initialization via cap_mediafoundation_utils::thread_init().
  • Signals readiness via oneshot channel after successful capturer creation and start.
  • Awaits ready result and only sets stop_tx on success, addressing previous review concerns.
  • Handles channel drop errors by returning a descriptive error.

The blocking stop_rx.recv() at line 474 keeps the thread alive until stop is signaled, which is appropriate for a dedicated capture thread.


503-527: LGTM: Stop coordination correctly propagates capturer results.

The refactored StopCapturing properly:

  • Guards against stopping when not capturing (lines 510-512).
  • Sends stop signal via stop_tx with a oneshot return channel (lines 514-517).
  • Awaits and propagates the stop result, including handling channel drop errors (lines 519-522), addressing previous review concerns.
  • Converts errors to String type per the updated reply signature.

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
Contributor

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ad9096 and 7538258.

📒 Files selected for processing (2)
  • crates/recording/examples/recording-cli.rs (1 hunks)
  • crates/recording/src/sources/screen_capture/windows.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/recording/examples/recording-cli.rs
  • crates/recording/src/sources/screen_capture/windows.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/recording/examples/recording-cli.rs
  • crates/recording/src/sources/screen_capture/windows.rs
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
🧬 Code graph analysis (1)
crates/recording/src/sources/screen_capture/windows.rs (3)
crates/recording/src/feeds/camera.rs (11)
  • oneshot (336-336)
  • handle (326-400)
  • handle (406-422)
  • handle (428-430)
  • handle (436-453)
  • handle (459-465)
  • handle (471-487)
  • handle (503-539)
  • handle (545-569)
  • handle (575-591)
  • handle (597-610)
crates/scap-direct3d/src/lib.rs (4)
  • new (140-335)
  • d3d_device (193-193)
  • d3d_device (345-347)
  • d3d_device (458-460)
crates/mediafoundation-utils/src/lib.rs (1)
  • thread_init (18-21)
⏰ 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: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Analyze (rust)

Copy link
Contributor

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7538258 and bc8a0d7.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml (1 hunks)
  • crates/recording/src/sources/screen_capture/windows.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
🧬 Code graph analysis (1)
crates/recording/src/sources/screen_capture/windows.rs (4)
crates/recording/src/feeds/camera.rs (11)
  • oneshot (336-336)
  • handle (326-400)
  • handle (406-422)
  • handle (428-430)
  • handle (436-453)
  • handle (459-465)
  • handle (471-487)
  • handle (503-539)
  • handle (545-569)
  • handle (575-591)
  • handle (597-610)
crates/scap-direct3d/src/lib.rs (4)
  • new (140-335)
  • d3d_device (193-193)
  • d3d_device (345-347)
  • d3d_device (458-460)
crates/mediafoundation-utils/src/lib.rs (1)
  • thread_init (18-21)
crates/recording/src/feeds/microphone.rs (3)
  • handle (245-365)
  • handle (371-383)
  • handle (389-391)
⏰ 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). (4)
  • GitHub Check: Clippy
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (5)
.github/workflows/ci.yml (1)

100-100: LGTM! Clippy component properly configured.

The addition of the clippy component ensures the linting tool is available during the CI build, supporting the Clippy check action that runs at line 128.

crates/recording/src/sources/screen_capture/windows.rs (4)

9-9: LGTM! Required imports for thread coordination.

The oneshot channel and StopCapturerError type support the new thread-based coordination model with ready signaling and stop result propagation.

Also applies to: 11-11


373-373: LGTM! Field change supports thread coordination.

The stop_tx field correctly replaces the direct capturer handle with a channel for coordinating stop requests and results with the dedicated thread.

Also applies to: 381-381


429-481: Thread coordination pattern correctly implements the fix.

The dedicated thread with thread_init() at line 436 addresses the COM marshalling issue mentioned in the PR objectives. The ready/stop channel coordination ensures proper lifecycle management:

  1. Thread initializes COM via thread_init() (fixes marshalling)
  2. Creates and starts capturer
  3. Signals readiness via ready_tx
  4. Blocks on stop_rx for shutdown signal
  5. Stops capturer and reports result

Frame and closed callbacks correctly use thread-safe channels (Recipient and flume::Sender), and the capturer is properly cleaned up when the thread exits.


496-519: LGTM! Stop coordination properly awaits worker thread result.

The StopCapturing handler correctly:

  • Takes ownership of stop_tx (line 503) ensuring single stop
  • Sends a oneshot channel to the worker thread (line 508)
  • Awaits the stop result via done_rx (lines 512-514)
  • Propagates errors from capturer.stop() as strings

The error at line 509 is logged when the worker thread has already exited, which is an acceptable fallback.

Copy link
Contributor

@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: 1

🧹 Nitpick comments (1)
crates/recording/src/sources/screen_capture/windows.rs (1)

503-503: Consider retaining typed error information.

The reply type changed from Result<(), StopCapturingError> to Result<(), String>, which loses type information and prevents callers from matching on specific error variants. While this simplification aligns with the current usage (where errors are ignored at line 328), consider whether preserving the typed error would benefit future callers or debugging.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc8a0d7 and 27bed99.

📒 Files selected for processing (1)
  • crates/recording/src/sources/screen_capture/windows.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
🧬 Code graph analysis (1)
crates/recording/src/sources/screen_capture/windows.rs (4)
crates/recording/src/feeds/camera.rs (11)
  • oneshot (336-336)
  • handle (326-400)
  • handle (406-422)
  • handle (428-430)
  • handle (436-453)
  • handle (459-465)
  • handle (471-487)
  • handle (503-539)
  • handle (545-569)
  • handle (575-591)
  • handle (597-610)
crates/scap-direct3d/src/lib.rs (4)
  • new (140-335)
  • d3d_device (193-193)
  • d3d_device (345-347)
  • d3d_device (458-460)
crates/mediafoundation-utils/src/lib.rs (1)
  • thread_init (18-21)
crates/recording/src/feeds/microphone.rs (3)
  • handle (245-365)
  • handle (371-383)
  • handle (389-391)
⏰ 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: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (3)
crates/recording/src/sources/screen_capture/windows.rs (3)

9-11: LGTM!

The new imports are correctly used for thread coordination (oneshot) and error handling (StopCapturerError).


373-381: LGTM!

The field replacement correctly reflects the new threading model, storing a channel to signal stop and receive results from the dedicated capturer thread.


416-499: LGTM!

The implementation correctly moves the Direct3D capturer onto a dedicated thread with proper ready/stop coordination:

  • Thread initialization calls thread_init() to set up COM/Media Foundation
  • Ready signal is awaited before returning, ensuring initialization errors surface synchronously
  • stop_tx is only set after successful startup, preventing stop attempts on failed initialization
  • Stop coordination properly waits for the signal, stops the capturer, and returns the result

This addresses the threading/marshalling issue mentioned in the PR objectives.

Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
crates/recording/src/sources/screen_capture/windows.rs (1)

519-525: Fix: Propagate channel drop error in stop coordination.

The if let Ok(res) pattern at line 519 silently ignores the Err case when done_rx.await fails (e.g., if the worker thread panics or drops the channel). This causes StopCapturing to incorrectly return Ok(()) at line 525 even though the stop result was never confirmed.

Apply this diff to propagate the error:

-        if let Ok(res) = done_rx.await {
-            res.map_err(|e| e.to_string())?;
-        }
+        match done_rx.await {
+            Ok(res) => res.map_err(|e| e.to_string())?,
+            Err(_) => return Err("Capturer thread dropped stop channel".to_string()),
+        }
 
         info!("stopped windows capturer");
 
         Ok(())
🧹 Nitpick comments (1)
crates/recording/src/sources/screen_capture/windows.rs (1)

514-517: Consider propagating stop signal send failure.

If stop_tx.send(done_tx) fails at line 515, the worker thread has already exited (channel disconnected). The current code logs the error but continues to await done_rx, which will never receive a value. Consider returning an error immediately instead of awaiting a channel that will never respond.

Apply this diff:

         let (done_tx, done_rx) = oneshot::channel();
-        if let Err(e) = stop_tx.send(done_tx) {
-            error!("Silently failed to stop Windows capturer: {}", e);
-        }
+        stop_tx
+            .send(done_tx)
+            .map_err(|_| "Worker thread already exited".to_string())?;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27bed99 and 3a09ae2.

📒 Files selected for processing (1)
  • crates/recording/src/sources/screen_capture/windows.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/recording/src/sources/screen_capture/windows.rs
🧬 Code graph analysis (1)
crates/recording/src/sources/screen_capture/windows.rs (4)
crates/recording/src/feeds/camera.rs (11)
  • oneshot (336-336)
  • handle (326-400)
  • handle (406-422)
  • handle (428-430)
  • handle (436-453)
  • handle (459-465)
  • handle (471-487)
  • handle (503-539)
  • handle (545-569)
  • handle (575-591)
  • handle (597-610)
crates/scap-direct3d/src/lib.rs (4)
  • new (140-335)
  • d3d_device (193-193)
  • d3d_device (345-347)
  • d3d_device (458-460)
crates/mediafoundation-utils/src/lib.rs (1)
  • thread_init (18-21)
crates/recording/src/feeds/microphone.rs (3)
  • handle (245-365)
  • handle (371-383)
  • handle (389-391)
⏰ 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: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (4)
crates/recording/src/sources/screen_capture/windows.rs (4)

9-9: LGTM: Import additions support thread coordination.

The futures::channel::oneshot and scap_direct3d::StopCapturerError imports are necessary for the new thread-based capturer lifecycle and stop coordination.

Also applies to: 11-11


373-373: LGTM: Field change aligns with thread-based architecture.

The replacement of capture_handle with stop_tx correctly reflects the new thread-based capturer lifecycle where stop coordination happens via channels rather than direct method calls.

Also applies to: 381-381


416-499: LGTM: StartCapturing correctly implements thread-based initialization.

The implementation properly:

  • Spawns a dedicated thread with COM initialization via cap_mediafoundation_utils::thread_init()
  • Signals readiness via oneshot channel after successful capturer creation
  • Awaits and propagates both success and failure from the ready channel before setting stop_tx
  • Blocks the worker thread waiting for stop coordination

This addresses the marshalling concerns mentioned in the PR description.


503-503: LGTM: Reply type simplified to String.

Changing the reply type from Result<(), StopCapturingError> to Result<(), String> simplifies error handling. The caller at line 328 already ignores the result, so this change is non-breaking.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Brendonovich Brendonovich merged commit bb2479f into main Oct 2, 2025
15 checks passed
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.

2 participants