Increase coverage#85
Conversation
📝 WalkthroughWalkthroughThe pull request updates continuous coverage collection, adds a shared WASM ignored-result helper, changes browser module result handling, coordinates graceful WebSocket runner shutdown, and adds configuration, path-resolution, timeout, and direct-message acknowledgement validation. ChangesCoverage persistence
WASM result handling
Runner shutdown coordination
Configuration and integration validation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ShutdownWatcher
participant run_agent
participant drive
ShutdownWatcher->>ShutdownWatcher: await Ctrl-C or RUNNER_TIMEOUT
ShutdownWatcher->>run_agent: notify shutdown
run_agent->>drive: pass Notify
drive->>drive: await shutdown signal
drive-->>run_agent: return successfully
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
|
Overall Grade |
Security Reliability Complexity Hygiene Coverage |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| C# | Jul 14, 2026 9:27a.m. | Review ↗ | |
| C & C++ | Jul 14, 2026 9:27a.m. | Review ↗ | |
| Docker | Jul 14, 2026 9:27a.m. | Review ↗ | |
| Java | Jul 14, 2026 9:27a.m. | Review ↗ | |
| JavaScript | Jul 14, 2026 9:27a.m. | Review ↗ | |
| Python | Jul 14, 2026 9:27a.m. | Review ↗ | |
| Rust | Jul 14, 2026 9:27a.m. | Review ↗ | |
| Secrets | Jul 14, 2026 9:27a.m. | Review ↗ | |
| Code coverage | Jul 14, 2026 9:48a.m. | Review ↗ |
Code Coverage Summary
| Language | Line Coverage (New Code) | Line Coverage (Overall) |
|---|---|---|
| Aggregate | 55.3% |
53.5% [▲ up 2.2% from main] |
| Python | - | 54.2% |
| Rust | 55.3% |
53.5% [▲ up 2.2% from main] |
➟ Additional coverage metrics may have been reported. See full coverage report ↗
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 9 |
| Duplication | 4 |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull Request Overview
This PR introduces graceful shutdown mechanisms and improved 'must_use' handling, but several issues must be addressed before merging. A high-priority fix is required for the non-standard usage of 'coreutils' in the coverage configuration, which will likely break CI environments. While the PR is titled 'Increase coverage', the provided coverage report is empty, and a required test scenario for LLVM continuous mode coverage persistence is missing. Additionally, the improvement in coverage is offset by the introduction of significant code duplication across six browser modules, which should be centralized to avoid increasing technical debt.
About this PR
- The coverage report provided is empty. Please ensure that coverage data is correctly generated and attached so that the quantitative impact of these changes can be verified.
- Please provide a detailed PR description. The current lack of context makes it difficult to verify if the implementation fully aligns with the intended architectural changes for coverage collection and runner lifecycle.
- There is a systemic inconsistency in how 'must_use' results are handled. While most modules were updated to use 'et_web::ignore', 'comm1' still uses 'let _status' in several places. Please standardize this across all modules modified in this PR.
3 comments outside of the diff
services/ws-modules/audio1/src/lib.rs
line 163🟡 MEDIUM RISK
This module uses the same boilerplate logic for logging, error description, and WebSocket connection as 5 other modules. Consider centralizing these common browser utilities into the 'et-web' library to reduce technical debt and maintenance overhead.
services/ws-modules/wasi-comm1/src/lib.rs
line 133⚪ LOW RISK
Suggestion: The 'wait_for_agent_id' and 'sleep_ms' functions are duplicated between the WASI modules. These should be moved to a common library to avoid diverging logic.
services/ws-pyo3-runner/src/agent.rs
line 171🟡 MEDIUM RISK
Suggestion: Replace 'storage_task.abort();' with 'let _ = storage_task.await;' to ensure the storage worker processes any final operations from the Python 'on_shutdown' hook before the process exits.
Test suggestions
- Verify pyo3-runner graceful shutdown on timeout triggers teardown and clean exit
- Verify project root resolution from the CARGO_MANIFEST_DIR environment
- Verify recipient acknowledgement notifies the sender with MessageDeliveryStatus::Acknowledged
- Verify coverage data persists for SIGKILLed processes using LLVM continuous mode
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify coverage data persists for SIGKILLed processes using LLVM continuous mode
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| # counters (`-Cllvm-args=-runtime-counter-relocation`). The wrapper flags env is CARGO_ENCODED_RUSTFLAGS format | ||
| # (ASCII unit separator 0x1f between flags), not space-separated -- a space append glues the llvm-arg onto the | ||
| # last existing flag and rustc rejects `--cfg=coverage_nightly -Cllvm-args=...` as one invalid --cfg value. | ||
| cov_dir="$(coreutils dirname "$LLVM_PROFILE_FILE")" |
There was a problem hiding this comment.
🔴 HIGH RISK
Invoke the utilities directly (e.g., 'dirname', 'uname') instead of prefixing them with 'coreutils' to ensure compatibility across standard shell environments.
| return; | ||
| }; | ||
| drop(serde_json::from_str::<ServerMessage>(&data)); | ||
| et_web::ignore(serde_json::from_str::<ServerMessage>(&data)); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
The call to 'serde_json::from_str' currently has no effect as the result is discarded. Remove this call if validation is not needed, or update it to log a warning (e.g., using 'tracing::warn!') if parsing fails to avoid silent diagnostic gaps.
| ); | ||
| web_sys::console::log_1(&JsValue::from_str(&line)); | ||
| drop(set_module_status(&line)); | ||
| let _status = set_module_status(&line); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: Use the newly introduced 'et_web::ignore' utility here instead of 'let _status'. This ensures consistency with other browser-based WASM modules updated in this PR and adheres to the project's workspace-wide linting strategy for 'must_use' results.
| let _status = set_module_status(&line); | |
| et_web::ignore(set_module_status(&line)); |
| let line = format!("comm1: invalid server response {message_id:?}: {detail}"); | ||
| web_sys::console::warn_1(&JsValue::from_str(&line)); | ||
| drop(set_module_status(&line)); | ||
| let _status = set_module_status(&line); |
There was a problem hiding this comment.
⚪ LOW RISK
Suggestion: Use 'et_web::ignore' for consistency with other browser-based WASM modules in this PR to discard the result of 'set_module_status'.
| let line = format!("comm1: message status update {message_id:?} {status:?}: {detail}"); | ||
| web_sys::console::log_1(&JsValue::from_str(&line)); | ||
| drop(set_module_status(&line)); | ||
| let _status = set_module_status(&line); |
There was a problem hiding this comment.
⚪ LOW RISK
Suggestion: Use 'et_web::ignore' for consistency with other browser-based WASM modules in this PR to discard the result of 'set_module_status'.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
services/ws-pyo3-runner/src/agent.rs (1)
119-161: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winRace
connect_and_register()with shutdown
run()still awaitsconnect_and_register(...)beforedrive(), soCtrl-C/RUNNER_TIMEOUTis ignored during startup. This is bounded by the defaultWS_CONNECT_ACK_TIMEOUT, but if that timeout is disabled (none/off/disabled) the process can stay stuck in connect/register until the server answers. Select onshutdown.notified()here too and tear down the partially initialized worker/socket on the shutdown branch.🤖 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 `@services/ws-pyo3-runner/src/agent.rs` around lines 119 - 161, Race the startup connect_and_register operation in run against shutdown.notified() so shutdown is honored even when the connection acknowledgment timeout is disabled. On shutdown, tear down the partially initialized Python worker and storage task before returning the appropriate shutdown result; preserve the existing registration, agent-id initialization, and drive flow when connection succeeds.
🧹 Nitpick comments (1)
services/ws-pyo3-runner/src/main.rs (1)
50-66: 🧹 Nitpick | 🔵 TrivialNo upper bound on teardown once shutdown is requested.
Once
shutdown.notify_one()fires,drive()returns promptly, butrun()'s subsequent teardown (worker.join(), awaiting the WS close send, the Pythonon_shutdownhook) has no timeout of its own.RUNNER_TIMEOUTnow only guarantees a prompt start of teardown, not a bounded total exit time — an unresponsive Pythonon_shutdownhook or a slow socket close could hang the process past the configured timeout. Worth considering a secondary bound (e.g. wrappingrun_agent(...)itself in an outertokio::time::timeoutthat force-exits if teardown doesn't complete promptly) as a safety net.🤖 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 `@services/ws-pyo3-runner/src/main.rs` around lines 50 - 66, Bound the entire run lifecycle, including teardown after shutdown notification, rather than applying RUNNER_TIMEOUT only to drive(). Update the run/run_agent flow around the shutdown watcher so the configured timeout also limits worker.join(), the WebSocket close, and the Python on_shutdown hook; force the existing shutdown/exit behavior when the outer timeout expires, while preserving normal completion and timeout-triggered shutdown handling.
🤖 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 `@libs/path/tests/find.rs`:
- Around line 11-15: Strengthen the assertion in the
find_project_root_from_manifest test to verify the resolved path is the
repository root, not merely an existing directory. Assert that
root.join(".dprint.jsonc").is_file() (or compare root with an independently
determined expected root), while retaining the existing directory validation if
useful.
In `@services/ws-pyo3-runner/src/main.rs`:
- Around line 46-67: Handle the io::Result returned by tokio::signal::ctrl_c()
in the shutdown watcher instead of treating every completion as an interrupt. In
the ctrl_c branch, log and propagate signal-handler installation errors so
run_agent does not perform an unintended shutdown, while preserving the existing
shutdown notification for a successful interrupt and the timeout path.
---
Outside diff comments:
In `@services/ws-pyo3-runner/src/agent.rs`:
- Around line 119-161: Race the startup connect_and_register operation in run
against shutdown.notified() so shutdown is honored even when the connection
acknowledgment timeout is disabled. On shutdown, tear down the partially
initialized Python worker and storage task before returning the appropriate
shutdown result; preserve the existing registration, agent-id initialization,
and drive flow when connection succeeds.
---
Nitpick comments:
In `@services/ws-pyo3-runner/src/main.rs`:
- Around line 50-66: Bound the entire run lifecycle, including teardown after
shutdown notification, rather than applying RUNNER_TIMEOUT only to drive().
Update the run/run_agent flow around the shutdown watcher so the configured
timeout also limits worker.join(), the WebSocket close, and the Python
on_shutdown hook; force the existing shutdown/exit behavior when the outer
timeout expires, while preserving normal completion and timeout-triggered
shutdown handling.
🪄 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: a358c962-0480-4dee-95f2-a15bb0a08495
📒 Files selected for processing (22)
.mise/config.coverage.tomlconfig/otelcol-hostmetrics.yamlconfig/ryl.yamllibs/path/tests/find.rslibs/web/src/lib.rsservices/ws-modules/audio1/src/lib.rsservices/ws-modules/bluetooth/src/lib.rsservices/ws-modules/comm1/src/lib.rsservices/ws-modules/data1/src/lib.rsservices/ws-modules/geolocation/src/lib.rsservices/ws-modules/graphics-info/src/lib.rsservices/ws-modules/har1/src/lib.rsservices/ws-modules/nfc/src/lib.rsservices/ws-modules/sensor1/src/lib.rsservices/ws-modules/speech-recognition/src/lib.rsservices/ws-modules/video1/src/lib.rsservices/ws-modules/wasi-comm1/src/lib.rsservices/ws-modules/wasi-data1/src/lib.rsservices/ws-pyo3-runner/src/agent.rsservices/ws-pyo3-runner/src/main.rsservices/ws-pyo3-runner/tests/modules.rsservices/ws-test-server/tests/direct_message_ack.rs
| let root = find_project_root_from_manifest(); | ||
| assert!( | ||
| root.is_dir(), | ||
| "resolved project root {root:?} should be an existing directory" | ||
| ); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert that the resolved path is the project root, not merely a directory.
root.is_dir() does not verify the helper walked to the repository root; returning any existing manifest directory would still pass. Assert that root.join(".dprint.jsonc").is_file() (or compare against an independently determined expected root) to exercise the actual contract.
🤖 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 `@libs/path/tests/find.rs` around lines 11 - 15, Strengthen the assertion in
the find_project_root_from_manifest test to verify the resolved path is the
repository root, not merely an existing directory. Assert that
root.join(".dprint.jsonc").is_file() (or compare root with an independently
determined expected root), while retaining the existing directory validation if
useful.
| // Graceful shutdown: ctrl_c or the optional RUNNER_TIMEOUT trips `shutdown`, which `run_agent`'s `drive` | ||
| // loop selects on. That returns the run loop so `run_agent` still executes its teardown (queue on_shutdown, | ||
| // join the Python worker, close the socket) instead of the run future being dropped mid-flight. The watcher | ||
| // runs concurrently and is abandoned when `run_agent` returns and the process exits. | ||
| let shutdown = std::sync::Arc::new(tokio::sync::Notify::new()); | ||
| let limit = config.runner.timeout; | ||
| let _watcher = tokio::spawn({ | ||
| let shutdown = std::sync::Arc::clone(&shutdown); | ||
| async move { | ||
| tokio::select! { | ||
| _ = tokio::signal::ctrl_c() => info!("interrupted; shutting down"), | ||
| () = async { | ||
| match limit { | ||
| Some(dur) => tokio::time::sleep(dur).await, | ||
| None => std::future::pending::<()>().await, | ||
| } | ||
| } => info!("run timeout {limit:?} elapsed; shutting down"), | ||
| } | ||
| shutdown.notify_one(); | ||
| } | ||
| }; | ||
|
|
||
| let Some(limit) = config.runner.timeout else { | ||
| driven.await?; | ||
| return Ok(()); | ||
| }; | ||
| let Ok(result) = tokio::time::timeout(limit, driven).await else { | ||
| info!("run timeout {limit:?} elapsed; shutting down"); | ||
| return Ok(()); | ||
| }; | ||
| result?; | ||
| }); | ||
| run_agent(agent, &shutdown).await?; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
ctrl_c() errors are silently treated as a real interrupt.
_ = tokio::signal::ctrl_c() => info!("interrupted; shutting down") discards the io::Result<()>. If installing the signal handler fails (rare, but possible, e.g. handler-limit exhaustion), the branch still resolves and this arm unconditionally logs "interrupted" and calls shutdown.notify_one(), causing an unintended shutdown rather than surfacing the real failure.
🛠️ Proposed fix to distinguish signal-install failure from a real interrupt
- _ = tokio::signal::ctrl_c() => info!("interrupted; shutting down"),
+ result = tokio::signal::ctrl_c() => match result {
+ Ok(()) => info!("interrupted; shutting down"),
+ Err(err) => {
+ warn!("failed to listen for ctrl_c: {err}");
+ return;
+ }
+ },📝 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.
| // Graceful shutdown: ctrl_c or the optional RUNNER_TIMEOUT trips `shutdown`, which `run_agent`'s `drive` | |
| // loop selects on. That returns the run loop so `run_agent` still executes its teardown (queue on_shutdown, | |
| // join the Python worker, close the socket) instead of the run future being dropped mid-flight. The watcher | |
| // runs concurrently and is abandoned when `run_agent` returns and the process exits. | |
| let shutdown = std::sync::Arc::new(tokio::sync::Notify::new()); | |
| let limit = config.runner.timeout; | |
| let _watcher = tokio::spawn({ | |
| let shutdown = std::sync::Arc::clone(&shutdown); | |
| async move { | |
| tokio::select! { | |
| _ = tokio::signal::ctrl_c() => info!("interrupted; shutting down"), | |
| () = async { | |
| match limit { | |
| Some(dur) => tokio::time::sleep(dur).await, | |
| None => std::future::pending::<()>().await, | |
| } | |
| } => info!("run timeout {limit:?} elapsed; shutting down"), | |
| } | |
| shutdown.notify_one(); | |
| } | |
| }; | |
| let Some(limit) = config.runner.timeout else { | |
| driven.await?; | |
| return Ok(()); | |
| }; | |
| let Ok(result) = tokio::time::timeout(limit, driven).await else { | |
| info!("run timeout {limit:?} elapsed; shutting down"); | |
| return Ok(()); | |
| }; | |
| result?; | |
| }); | |
| run_agent(agent, &shutdown).await?; | |
| // Graceful shutdown: ctrl_c or the optional RUNNER_TIMEOUT trips `shutdown`, which `run_agent`'s `drive` | |
| // loop selects on. That returns the run loop so `run_agent` still executes its teardown (queue on_shutdown, | |
| // join the Python worker, close the socket) instead of the run future being dropped mid-flight. The watcher | |
| // runs concurrently and is abandoned when `run_agent` returns and the process exits. | |
| let shutdown = std::sync::Arc::new(tokio::sync::Notify::new()); | |
| let limit = config.runner.timeout; | |
| let _watcher = tokio::spawn({ | |
| let shutdown = std::sync::Arc::clone(&shutdown); | |
| async move { | |
| tokio::select! { | |
| result = tokio::signal::ctrl_c() => match result { | |
| Ok(()) => info!("interrupted; shutting down"), | |
| Err(err) => { | |
| warn!("failed to listen for ctrl_c: {err}"); | |
| return; | |
| } | |
| }, | |
| () = async { | |
| match limit { | |
| Some(dur) => tokio::time::sleep(dur).await, | |
| None => std::future::pending::<()>().await, | |
| } | |
| } => info!("run timeout {limit:?} elapsed; shutting down"), | |
| } | |
| shutdown.notify_one(); | |
| } | |
| }); | |
| run_agent(agent, &shutdown).await?; |
🤖 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 `@services/ws-pyo3-runner/src/main.rs` around lines 46 - 67, Handle the
io::Result returned by tokio::signal::ctrl_c() in the shutdown watcher instead
of treating every completion as an interrupt. In the ctrl_c branch, log and
propagate signal-handler installation errors so run_agent does not perform an
unintended shutdown, while preserving the existing shutdown notification for a
successful interrupt and the timeout path.
Summary by CodeRabbit