Skip to content

Increase coverage#85

Merged
jayvdb merged 3 commits into
mainfrom
more-rs-coverage
Jul 14, 2026
Merged

Increase coverage#85
jayvdb merged 3 commits into
mainfrom
more-rs-coverage

Conversation

@jayvdb

@jayvdb jayvdb commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added graceful shutdown handling for the WebSocket runner when interrupted or when its configured timeout expires.
  • Bug Fixes
    • Improved coverage collection so data is preserved when runner processes are forcibly terminated.
  • Tests
    • Added coverage for graceful timeout shutdowns and direct-message acknowledgement delivery.
  • Chores
    • Strengthened YAML comment indentation validation.
    • Standardized handling of intentionally ignored operation results across browser modules.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The 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.

Changes

Coverage persistence

Layer / File(s) Summary
Continuous coverage instrumentation
.mise/config.coverage.toml
Coverage uses per-process continuous profraw files and Linux counter-relocation flags for profile persistence.

WASM result handling

Layer / File(s) Summary
Shared ignored-result helper
libs/web/src/lib.rs
Adds the public generic ignore helper for intentionally discarded values.
Browser module result handling
services/ws-modules/*/src/lib.rs
Replaces explicit result drops around browser callbacks, timers, lifecycle operations, rendering, and status updates with et_web::ignore(...) or ignored bindings.
WASI polling result handling
services/ws-modules/wasi-*/src/lib.rs
Stores polling results in throwaway locals without changing sleep behavior.

Runner shutdown coordination

Layer / File(s) Summary
Shutdown signal propagation
services/ws-pyo3-runner/src/agent.rs
Passes a Notify shutdown signal into the WebSocket drive loop, which exits when notified.
Watcher and runner orchestration
services/ws-pyo3-runner/src/main.rs
Coordinates Ctrl-C and RUNNER_TIMEOUT through a watcher task and shared shutdown notifier.
Graceful timeout validation
services/ws-pyo3-runner/tests/modules.rs
Adds a timeout shutdown integration test and centralizes the RUST_LOG variable name.

Configuration and integration validation

Layer / File(s) Summary
Repository lint and path validation
config/ryl.yaml, libs/path/tests/find.rs
Enforces comment indentation errors and tests manifest-based project-root resolution.
Host metrics receiver guidance
config/otelcol-hostmetrics.yaml
Updates commented GPU/DCGM receiver guidance.
Direct-message acknowledgement validation
services/ws-test-server/tests/direct_message_ack.rs
Tests acknowledgement delivery and preservation of the original direct-message ID.

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
Loading

Possibly related PRs

  • edge-toolkit/core#84: Related changes also replace explicit result-discarding patterns in WebSocket code.

Suggested reviewers: pierre-tenedero

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main goal of the changeset, which adds tests and coverage-related tooling to increase code coverage.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ 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 more-rs-coverage

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

@deepsource-io

deepsource-io Bot commented Jul 14, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in f469545...97f1434 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

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.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 9 complexity · 4 duplication

Metric Results
Complexity 9
Duplication 4

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

@jayvdb
jayvdb marked this pull request as ready for review July 14, 2026 09:34
@jayvdb
jayvdb requested a review from pierre-tenedero July 14, 2026 09:34

@codacy-production codacy-production 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.

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")"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 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));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 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.

Suggested change
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ 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'.

@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

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 win

Race connect_and_register() with shutdown
run() still awaits connect_and_register(...) before drive(), so Ctrl-C/RUNNER_TIMEOUT is ignored during startup. This is bounded by the default WS_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 on shutdown.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 | 🔵 Trivial

No upper bound on teardown once shutdown is requested.

Once shutdown.notify_one() fires, drive() returns promptly, but run()'s subsequent teardown (worker.join(), awaiting the WS close send, the Python on_shutdown hook) has no timeout of its own. RUNNER_TIMEOUT now only guarantees a prompt start of teardown, not a bounded total exit time — an unresponsive Python on_shutdown hook or a slow socket close could hang the process past the configured timeout. Worth considering a secondary bound (e.g. wrapping run_agent(...) itself in an outer tokio::time::timeout that 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

📥 Commits

Reviewing files that changed from the base of the PR and between f469545 and 97f1434.

📒 Files selected for processing (22)
  • .mise/config.coverage.toml
  • config/otelcol-hostmetrics.yaml
  • config/ryl.yaml
  • libs/path/tests/find.rs
  • libs/web/src/lib.rs
  • services/ws-modules/audio1/src/lib.rs
  • services/ws-modules/bluetooth/src/lib.rs
  • services/ws-modules/comm1/src/lib.rs
  • services/ws-modules/data1/src/lib.rs
  • services/ws-modules/geolocation/src/lib.rs
  • services/ws-modules/graphics-info/src/lib.rs
  • services/ws-modules/har1/src/lib.rs
  • services/ws-modules/nfc/src/lib.rs
  • services/ws-modules/sensor1/src/lib.rs
  • services/ws-modules/speech-recognition/src/lib.rs
  • services/ws-modules/video1/src/lib.rs
  • services/ws-modules/wasi-comm1/src/lib.rs
  • services/ws-modules/wasi-data1/src/lib.rs
  • services/ws-pyo3-runner/src/agent.rs
  • services/ws-pyo3-runner/src/main.rs
  • services/ws-pyo3-runner/tests/modules.rs
  • services/ws-test-server/tests/direct_message_ack.rs

Comment thread libs/path/tests/find.rs
Comment on lines +11 to +15
let root = find_project_root_from_manifest();
assert!(
root.is_dir(),
"resolved project root {root:?} should be an existing directory"
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Comment on lines +46 to +67
// 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?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 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.

Suggested change
// 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.

@jayvdb
jayvdb merged commit 9fd83d3 into main Jul 14, 2026
31 of 34 checks passed
@jayvdb
jayvdb deleted the more-rs-coverage branch July 14, 2026 10:45
@coderabbitai coderabbitai Bot mentioned this pull request Jul 23, 2026
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