Skip to content

fix(telemetry): report real battery % while charging#10943

Open
ndoo wants to merge 2 commits into
meshtastic:developfrom
mesh-malaysia:fix/telemetry-battery-level-charging
Open

fix(telemetry): report real battery % while charging#10943
ndoo wants to merge 2 commits into
meshtastic:developfrom
mesh-malaysia:fix/telemetry-battery-level-charging

Conversation

@ndoo

@ndoo ndoo commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

Related to #10906.

device_metrics.battery_level is forced to the 101 sentinel (MAGIC_USB_BATTERY_LEVEL) whenever isCharging() is true, on any board, regardless of which mechanism makes it trueEXT_CHRG_DETECT/EXT_PWR_DETECT pins, a PMU/fuel-gauge's own charge-status bit, or plain USB power detection. This is a pre-existing, general bug, not specific to any one board or introduced by any one PR: it masks the real number for the whole 0-99% charge ramp on every board where charge detection works at all, and always has.

I noticed it after #10906 merged: my device — which monitors the STBY→EXT_PWR_DETECT and CHRG→EXT_CHRG_DETECT pins of a TP4057 — reported battery_level as 101 for the entire charge cycle instead of the real percentage.1 #10906 didn't introduce this, though — it's independent of that PR's actual changes. Any board where charge detection already worked before #10906 hits the same masking, and any future fix to charge detection on another board (like #10941, filed alongside this PR) will surface it there too.

Protobufs as the source of truth

telemetry.proto documents battery_level as 0-100 (>100 means powered)2101 means "no reading available," not "currently charging." This PR treats that contract as authoritative throughout: a real reading is real data and gets reported as such, never overridden by an inferred charge state. That's the standard the fix below, and the 100%-edge-case decision after it, are both held to.

Fix

Fall back to the sentinel only when there's no trustworthy reading at all (!hasBattery). Every real reading, including 100% while still charging, is now reported as-is.

Telemetry sentinel logic

The full truth table over the two inputs the sentinel actually reads:

hasBattery isCharging() battery_level before battery_level after
true true 101 real %
true false real % real % (unaffected)
false true 101 101 (unaffected)
false false 101 101 (unaffected)

Only the first row changes. On real hardware, EXT_CHRG_DETECT (when present) decides isCharging() outright, regardless of EXT_PWR_DETECT; without it, EXT_PWR_DETECT alone decides. hasBattery is false for boards with no battery-sensing hardware at all, and for battery hardware present with no cell inserted. After this fix, it no longer matters which signal makes either input true — only whether a reading exists (hasBattery) and, when it does, what the reading is. That includes real % landing on exactly 100 while isCharging() is true — see The 100%-while-charging edge case, below.

The same rule as a flowchart, after this PR — isCharging() no longer appears at all:

flowchart TD
    HB{hasBattery?} -->|no| S["battery_level = 101"]
    HB -->|yes| R["battery_level = real %"]
Loading

Compare against Appendix: battery_level sentinel logic before this PR, below, where isCharging() forces 101 on its own, independent of hasBattery.

The 100%-while-charging edge case

A node at exactly 100% while still charging now reports 100, not 101. 101 was previously used there to preserve "this node is currently powered" as a mesh-visible signal, but that would violate the contract above: the commit that introduced >100 means powered3 shows the sentinel was meant to mean "no real reading exists," not to override a valid one.

It also conflicts with iOS's BatteryLevel.swift4, which already special-cases battery_level == 100 for its "topped-up-and-charging" icon — reporting 101 there defeats it.

This affects one value: a node at exactly 100% while charging can no longer be distinguished, over the mesh, from a node at 100% that's simply sitting fully charged and unplugged. Every value from 0 to 99 already loses that same distinction under this fix (see Regression scope); a real is_charging field is the right way to recover it for all of them (see Future work).

Groundwork: centralizing PowerState

StatusLEDModule needs a reliable, per-board-correct charge state for its own LED cadence. On develop, it derives that state privately.5 This PR moves the derivation into PowerStatus::getPowerState() instead, and hardens it with an explicit Unknown = 0 default, so a future is_charging-style field (see Future work) has a stable, ready-made source to map onto directly.

LED behavior is unchanged — this is groundwork, not a fix on its own — and it's unaffected by the 101100 change above: getPowerState()'s solid-LED Charged state triggers on getBatteryChargePercent() >= 1006, so a node landing on a real 100 still crosses that threshold the same as 101 did.

PowerStatus::getPowerState(), after this PR — highlighted nodes are the only part this PR actually changes; everything else is StatusLEDModule's pre-existing derivation, relocated unmodified (compare against Appendix: PowerState derivation before this PR, below):

flowchart TD
    I{initialized?} -->|no| U[Unknown]
    I -->|yes| P{"USB present or\nisCharging()"}
    P -->|no| L{percent > 5}
    L -->|yes| DIS[Discharging]
    L -->|no| CRIT[Critical]
    P -->|yes| F{percent ≥ 100}
    F -->|yes| CHGD[Charged]
    F -->|no| CHG[Charging]

    style I fill:#ffe28a,stroke:#a86b00,stroke-width:3px,color:#000000
    style U fill:#ffe28a,stroke:#a86b00,stroke-width:3px,color:#000000
Loading

StatusLEDModule reads this directly: Charging blinks ~1Hz, Charged solid on, Discharging a brief once-a-second heartbeat flash, Critical a fast 250ms blink.

Regression scope & client impact

  • No change for boards with no battery sensing — battery_level stays 101 unconditionally.
  • Boards with a working battery reading (the common case, fuel-gauge/PMU included) now report the real, live percentage while charging, 0-100, instead of 101 — including at exactly 100%, where the mesh can no longer tell "still powered" apart from "idle" (see The 100%-while-charging edge case, above).
  • Not touched: pico2_w5500_e22 (NO_BATTERY_LEVEL_ON_CHARGE7) — still shows 0% while charging, matching its own local display; forcing it to 101 too would require breaking isCharging()'s fallback, the JSON HTTP API's is_charging field, and the debug overlay.

Checked Android8, iOS4, and device-ui9 main-branch source directly: none treat 1-99 as a charging indicator, so no existing signal is removed there. This repo's own on-device Base UI (the OLED screen's remote-node status line, UIRenderer.cpp)10 has the identical bug directly: it shows "Plugged In" in place of any percentage whenever battery_level > 100, so a remote node's entry froze at "Plugged In" for its whole charge cycle too — this fix restores the live percentage there as well. Across all four, the only remaining visible change is at exactly 100%, discussed above.

Testing

Build-verified: tracker-t1000-e, pico2_w5500_e22, russell, thinknode_m6.

Hardware-verified:

hasBattery/isCharging() are derived differently board to board — EXT_CHRG_DETECT/EXT_PWR_DETECT pins, a PMU/fuel-gauge's own charge-status bit, a generic ADC voltage divider, or board-specific overrides like ELECROW_ThinkNode_M6's branch. The three boards above don't cover that whole matrix, so maintainer/community testing on other commonly-used devices (see Attestations) would help catch any board-specific surprises this session didn't exercise.

Native unit tests didn't run locally (pre-existing toolchain issues, unrelated to this change). No existing test covers this logic.

Future work

DeviceMetrics has no is_charging field12, so nothing downstream can distinguish "charging" from "discharging at some percentage" — and after this fix, battery_level no longer tries to carry that signal at all. The groundwork above (PowerStatus::getPowerState()) is what's missing to build it properly: a protobufs schema change, populating it in DeviceTelemetry.cpp from getPowerState(), and client updates (Android/iOS/device-ui) to consume it instead of inferring from battery_level.

The local JSON HTTP API already validates this need: it exposes powerStatus->getIsCharging()13 directly to a directly-connected client, but only as a raw boolean, only for WiFi/Ethernet boards, and only over HTTP — not over the mesh. A second, complementary route would generalize that same idea properly: expose getPowerState() through the admin protobuf instead, so any companion app connected to a node (BLE/serial/TCP, not just WiFi/Ethernet HTTP) can query its power/charging status as the richer Discharging/Charging/Charged/Critical state, rather than a plain boolean or an inference from battery_level. Unlike the DeviceMetrics field above, this wouldn't need a mesh-wide telemetry broadcast — just a direct connection to that node. AdminMessage, as defined on develop, has no such request/response.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other: hardware flash+boot on T-Echo, T-Beam S3 Core (tbeam-s3-core), and Seeed Wio Tracker L1 — all boot clean; build-only for tracker-t1000-e, pico2_w5500_e22, russell, thinknode_m6.

Appendix: battery_level sentinel logic before this PR

Provided for comparison against the flowchart in Telemetry sentinel logic, above. On develop, isCharging() forces 101 on its own, independent of hasBattery — the source of the bug this PR fixes:

flowchart TD
    HB{hasBattery?} -->|no| S1["battery_level = 101"]
    HB -->|yes| IC{isCharging?}
    IC -->|yes| S2["battery_level = 101"]
    IC -->|no| R["battery_level = real %"]

    style IC fill:#ffe28a,stroke:#a86b00,stroke-width:3px,color:#000000
    style S2 fill:#ffe28a,stroke:#a86b00,stroke-width:3px,color:#000000
Loading

Highlighted: the isCharging() branch this PR removes. After this PR, only hasBattery decides the sentinel (see the flowchart in Telemetry sentinel logic, above).

Appendix: PowerState derivation before this PR

Provided for comparison against the flowchart in Groundwork: centralizing PowerState, above. This is StatusLEDModule's private derivation on develop5, not PowerStatus::getPowerState() — that function doesn't exist before this PR.

StatusLEDModule's private derivation, on develop, before this PR:

flowchart TD
    P{"USB present or\nisCharging()"} -->|no| L{percent > 5}
    L -->|yes| DIS[discharging]
    L -->|no| CRIT[critical]
    P -->|yes| F{percent ≥ 100}
    F -->|yes| CHGD[charged]
    F -->|no| CHG[charging]
Loading

No Unknown state exists before this PR: power_state defaults to discharging at declaration, so the LED assumes discharging cadence until the first STATUS_TYPE_POWER update arrives, rather than an explicit unset state.


Summary by CodeRabbit

  • New Features

    • Added a unified power state for devices, with clearer states like Unknown, Charging, Charged, Discharging, and Critical.
    • Device telemetry now reports the actual battery percentage even while charging on battery-powered devices.
  • Bug Fixes

    • Improved power/LED behavior by using a consistent power state across the app.
    • Heartbeat and critical-power indicators now respond more accurately to the current charging state.

Footnotes

  1. Comment on #10906.

  2. protobufs/meshtastic/telemetry.proto#L14-L18DeviceMetrics.battery_level doc comment.

  3. protobufs@b546551 — "Make power level less dumb," the commit that introduced >100 means powered (replacing 0 means powered).

  4. BatteryLevel.swift#L16-L51 — special-cases == 100 and > 100 separately. 2

  5. src/modules/StatusLEDModule.cpp#L51-L61 (pre-refactor) — the charge/power state derivation this PR moves into PowerStatus::getPowerState(). 2

  6. src/PowerStatus.h#L72getPowerState()'s Charged threshold (introduced in this PR; not yet on develop).

  7. src/Power.cpp#L361 and variants/rp2350/diy/pico2_w5500_e22/variant.h#L30 — the only board defining NO_BATTERY_LEVEL_ON_CHARGE.

  8. BuildNodeDescription.kt#L116 (if (it in 1..MAX_BATTERY_PERCENT), where MAX_BATTERY_PERCENT = 100 at L39) and LocalStatsWidget.kt#L184 (state.batteryLevel > 100) — both key off battery_level > 100.

  9. BatteryLevel.cpp#L21-L22 — needs percentage >= 100 and voltage > CHARGING_VOLTAGE (4.30) for its Charging icon.

  10. src/graphics/draw/UIRenderer.cpp#L1060-L1073 — the remote-node battery-status line's pct > 100 → "Plugged In" branch.

  11. src/Power.cpp#L391 (OCV-curve interpolation, clamped [0, 100]) and MAX17048Sensor.cpp#L76 (fuel gauge, same clamp).

  12. protobufs/meshtastic/telemetry.proto#L14-L39 — full DeviceMetrics message.

  13. src/mesh/http/ContentHandler.cpp#L758.

ndoo added 2 commits July 8, 2026 23:59
StatusLEDModule re-derived charge/power state (discharging/charging/
charged/critical) from getHasUSB()/getIsCharging()/getBatteryChargePercent()
independently of other consumers of the same signals. Move it to
PowerStatus::getPowerState() so there's one source of truth; StatusLEDModule
now just reads it. LED behavior unchanged.

Also hoists the pre-existing power_state != Charging && power_state !=
Charged guard (duplicated across the LED_HEARTBEAT #if/#else branches)
into a single local, since both copies needed the new qualified enum
name anyway.

Hardened PowerState itself: explicit numbering with Unknown = 0 as the
default/unset value (was unnumbered, no Unknown), and getPowerState()
now returns Unknown before the first real reading arrives instead of
guessing from all-default fields. StatusLEDModule's default member
initializer moves from Discharging to Unknown to match - runOnce()
only branches on Charging/Charged/Critical, so anything else (including
Unknown) still falls through to the same heartbeat default; no LED
behavior change. This gives a future is_charging-style protobuf field
a stable, ready-made source to map onto directly.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Andrew Yong <me@ndoo.sg>
Client-visible behavior change: nodes that are actively charging (plugged
in, battery below 100%) now report their real battery percentage in mesh
telemetry (device_metrics.battery_level) instead of the fixed sentinel 101.
Apps/dashboards that show a node's live battery % while it charges will
start seeing it move again instead of being pinned at 101/powered for the
whole charge cycle.

Root cause: battery_level was forced to MAGIC_USB_BATTERY_LEVEL (101)
whenever isCharging() was true, at any percentage, masking the real number
for the whole 0-99% charge ramp - on any board where charge detection
works, regardless of which mechanism drives isCharging() (EXT_CHRG_DETECT/
EXT_PWR_DETECT pins, a PMU/fuel-gauge's own charge-status bit, or plain USB
power detection). This is a pre-existing, general bug independent of
meshtastic#10906. I noticed it after meshtastic#10906 merged, on my own device (a TP4057
charger wired to STBY->EXT_PWR_DETECT and CHRG->EXT_CHRG_DETECT), which
reported 101 for its entire charge cycle instead of the real percentage.

telemetry.proto documents battery_level as "0-100 (>100 means powered)" -
101 means "no reading available," not "currently charging."

Fix: key the sentinel off !hasBattery alone. hasBattery is false whenever
there's genuinely no battery ADC/fuel-gauge/PMU on the board, or battery
hardware present with no cell inserted; every other board (the common
case, including fuel-gauge/PMU boards) now reports its real percentage
while charging, 0 through 100 - including a real 100% while still
powered, previously reported as 101. Overriding that real 100% reading
with 101 would violate the >100-means-powered contract (protobufs commit
b546551 replaced an earlier "0 means powered" convention specifically to
get an unambiguous "no real reading exists" sentinel, not a modifier
meant to override a valid reading), and conflicts with iOS's
BatteryLevel.swift, which already special-cases battery_level == 100 for
its "topped-up-and-charging" bolt icon. The cost - losing "powered at
exactly 100%" as a mesh-visible signal - is the same cost every other
percentage already pays under this fix; a real is_charging field is the
right way to recover it, not an overloaded battery_level.

Deliberately not touched: boards defining NO_BATTERY_LEVEL_ON_CHARGE
(today: only pico2_w5500_e22), whose getBatteryPercent() returns a
placeholder 0 while charging because their voltage reading is untrusted
then. Flipping hasBattery false for that board's whole charge cycle would
break isCharging()'s own fallback formula, the JSON HTTP status API's
is_charging field, and the on-device debug overlay. Showing 0% while
charging there matches its own local display and is out of scope here.

Client impact: checked Android, iOS and device-ui source directly. None
treat 1-99 as a charging indicator, so no client-visible signal is removed
there - the 0-99% ramp goes from hidden/frozen to live. At exactly 100%,
iOS's bolt icon and device-ui's charging icon (both keyed off
battery_level/percentage == 100) now trigger correctly instead of being
defeated by the old 101 override; Android's ">100 means powered" text
narrows from "Powered" to "100%" at that one value. This repo's own
on-device Base UI (UIRenderer.cpp's remote-node status line) had the
identical bug: it shows "Plugged In" in place of any percentage whenever
battery_level > 100, so a remote node's entry froze at "Plugged In" for
its whole charge cycle too - this fix restores the live percentage there
as well.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Andrew Yong <me@ndoo.sg>
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a shared meshtastic::PowerState enum with a PowerStatus::getPowerState() accessor that derives a coarse charge state from existing fields. StatusLEDModule is migrated to use this shared enum instead of its local one. DeviceTelemetry now reports actual battery percent while charging instead of a magic USB sentinel.

Changes

Coarse Power State Unification

Layer / File(s) Summary
PowerState enum and derivation method
src/PowerStatus.h
Adds PowerState enum class (Unknown, Discharging, Charging, Charged, Critical) and getPowerState() method deriving state from init status, USB/charging flags, and battery percent thresholds.
StatusLEDModule migration to shared PowerState
src/modules/StatusLEDModule.h, src/modules/StatusLEDModule.cpp
Replaces local PowerState enum with meshtastic::PowerState, assigns power_state directly from getPowerState(), updates LED and heartbeat comparisons to use the new enum and a notCharging predicate.
DeviceTelemetry battery level reporting
src/modules/Telemetry/DeviceTelemetry.cpp
Narrows the MAGIC_USB_BATTERY_LEVEL condition to batteryless devices only, so charge percent is reported during charging.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PowerStatus
  participant StatusLEDModule
  participant LEDs

  StatusLEDModule->>PowerStatus: getPowerState()
  PowerStatus-->>StatusLEDModule: PowerState (Charging/Charged/Discharging/Critical/Unknown)
  StatusLEDModule->>StatusLEDModule: compute notCharging
  StatusLEDModule->>LEDs: update charge LED based on Charging/Charged
  StatusLEDModule->>LEDs: update power LED based on Critical
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title is concise and accurately summarizes the main telemetry change about reporting the real battery percentage while charging.
Description check ✅ Passed The description is detailed and covers problem, fix, testing, and attestations, matching the repository template well enough.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@ndoo

ndoo commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

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.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Note

Building this pull request… the flash button, badges and supported-board
list will appear here automatically once CI finishes.

@github-actions github-actions Bot added the bugfix Pull request that fixes bugs label Jul 8, 2026

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

🧹 Nitpick comments (2)
src/PowerStatus.h (2)

14-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Comment exceeds 1–2 line guideline.

This 3-line doc comment exceeds the repo's comment-length guideline for C++ files.

✏️ Suggested trim
-/// Coarse charge/power state, derived from PowerStatus's own fields.
-/// Explicitly numbered, with Unknown=0 as the default/unset value, so this can be wire-mapped to a future
-/// protobuf enum (e.g. an admin/telemetry is_charging-style field) without the numbering shifting under it.
+/// Coarse charge/power state, derived from PowerStatus's own fields.
+/// Explicitly numbered (Unknown=0) so future wire-mapping to a protobuf enum is stable.
 enum class PowerState { Unknown = 0, Discharging = 1, Charging = 2, Charged = 3, Critical = 4 };

As per coding guidelines, "Keep code comments minimal: one or two lines maximum, only when the reason is not obvious, and do not restate the next line."

🤖 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 `@src/PowerStatus.h` around lines 14 - 17, Shorten the doc comment above
PowerState in PowerStatus.h to fit the one-or-two-line C++ comment guideline.
Keep only the essential rationale for the enum’s explicit numbering and
Unknown=0 default, and remove the extra explanatory sentence so the comment does
not restate obvious code behavior.

Source: Coding guidelines


64-75: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Same comment-length guideline applies here.

This doc comment on getPowerState() also spans 3 lines.

Separately, worth verifying: for boards without a battery pin/PMU (getBatteryChargePercent() returns the 101 sentinel when !getHasBattery()), if getHasUSB()/getIsCharging() are ever both false while the sentinel is 101, this method falls into the final branch and returns Discharging (since 101 > 5) rather than something reflecting "powered, no battery sensor." This may be an unreachable combination in practice (such boards are typically always externally powered), but since this method is now the shared source of truth intended for future richer charging-state reporting, it's worth confirming the assumption holds for all board variants.

🤖 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 `@src/PowerStatus.h` around lines 64 - 75, Shorten the doc comment on
getPowerState() to comply with the comment-length guideline, and verify the
no-battery sentinel path in getPowerState() is safe for all boards. In
particular, confirm that getBatteryChargePercent() returning 101 when
getHasBattery() is false cannot reach the final Discharging branch when
getHasUSB() and getIsCharging() are both false; if that combination is possible,
update getPowerState() to return a state that explicitly reflects “powered, no
battery sensor” instead of treating it as Discharging.

Source: Coding guidelines

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

Nitpick comments:
In `@src/PowerStatus.h`:
- Around line 14-17: Shorten the doc comment above PowerState in PowerStatus.h
to fit the one-or-two-line C++ comment guideline. Keep only the essential
rationale for the enum’s explicit numbering and Unknown=0 default, and remove
the extra explanatory sentence so the comment does not restate obvious code
behavior.
- Around line 64-75: Shorten the doc comment on getPowerState() to comply with
the comment-length guideline, and verify the no-battery sentinel path in
getPowerState() is safe for all boards. In particular, confirm that
getBatteryChargePercent() returning 101 when getHasBattery() is false cannot
reach the final Discharging branch when getHasUSB() and getIsCharging() are both
false; if that combination is possible, update getPowerState() to return a state
that explicitly reflects “powered, no battery sensor” instead of treating it as
Discharging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 57271e0d-f73b-42e8-82f7-afac0999a789

📥 Commits

Reviewing files that changed from the base of the PR and between ade4283 and a3b7266.

📒 Files selected for processing (4)
  • src/PowerStatus.h
  • src/modules/StatusLEDModule.cpp
  • src/modules/StatusLEDModule.h
  • src/modules/Telemetry/DeviceTelemetry.cpp

@ndoo ndoo marked this pull request as ready for review July 8, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Pull request that fixes bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant