Skip to content

fix: pre-release ghost hears, 24h clock hydrate, and i18n accuracy - #782

Merged
rinchen merged 5 commits into
mainfrom
update
Aug 3, 2026
Merged

fix: pre-release ghost hears, 24h clock hydrate, and i18n accuracy#782
rinchen merged 5 commits into
mainfrom
update

Conversation

@rinchen

@rinchen rinchen commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Complete MeshCore BLE ghost-node suppression on PacketRouter + node side effects (node_info / position / telemetry), and only store parseable BLE MACs so Linux Web BT UUIDs cannot fake Meshtastic last_heard bumps.
  • Hydrate use24HourTime from SQLite on App mount so Chat/Diagnostics do not keep a stale localStorage clock until the App tab opens.
  • Fix post-v5.25.0 locale false friends (hub→backbone CTAs, Nomad countdown “left”, anatomy backbone labels, zh tabAll, ja I2P spacing, path/guidance copy) and add check-i18n-quality guards.
  • Includes the aborted-release lockfile bump (baseline-browser-mapping).

Test plan

  • pnpm exec vitest run src/renderer/lib/meshtastic/meshtasticNodeSideEffects.test.ts src/renderer/lib/drivers/PacketRouter.test.ts src/renderer/lib/connectedMeshcoreBleMac.test.ts src/renderer/runtime/useMeshcoreRuntime.reconnect.test.ts src/renderer/stores/timeFormatStore.test.ts scripts/check-i18n-quality.test.mjs
  • pnpm run check:i18n
  • Dual-radio: MeshCore BLE connected + Meshtastic RF hearing the same hardware — ghost node must not stay “Just now”
  • Toggle 24h clock, quit/relaunch without opening App tab — Chat timestamps match SQLite preference
  • Spot-check fr/es/zh/ja backbone picker title + Nomad loading countdown

Summary by CodeRabbit

  • Bug Fixes
    • Prevented duplicate or “ghost” Meshtastic nodes from appearing when connected through MeshCore BLE.
    • Improved BLE identity handling across connections and reconnects.
    • Preserved the selected 12-hour or 24-hour time format when launching the app.
    • Corrected several localized translations and formatting issues across Spanish, Chinese, French, and Japanese.
  • Tests
    • Added regression coverage for BLE node filtering, time-format restoration, and translation quality.

rinchen added 4 commits August 3, 2026 10:27
Wire MAC-based ghost suppression through PacketRouter and node side
effects, and only store parseable BLE MACs so Linux Web BT UUIDs cannot
pretend to be radios for Meshtastic last_heard bumps.
AppPanel is lazy, so Chat and other panels could keep a stale
localStorage clock until the App tab was opened. Reconcile early from
app_settings like locale.
Align hub→backbone picker/CTA copy, Nomad countdown “left”, anatomy
backbone labels, zh tabAll, ja I2P spacing, and related path/guidance
strings; gate regressions in check-i18n-quality.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@rinchen, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: be3e14ed-4143-496e-9c72-26d88c737b58

📥 Commits

Reviewing files that changed from the base of the PR and between 2837cdd and e852760.

📒 Files selected for processing (2)
  • scripts/check-i18n-quality.test.mjs
  • src/renderer/lib/drivers/PacketRouter.test.ts
📝 Walkthrough

Walkthrough

The PR adds pre-release locale checks, hydrates the time-format store from SQLite at startup, and derives valid MeshCore BLE MACs for Meshtastic ghost-node suppression across runtime, packet routing, and node side effects.

Changes

Locale quality validation

Layer / File(s) Summary
Pre-release locale accuracy checks
scripts/check-i18n-quality.mjs, scripts/check-i18n-quality.test.mjs
The checker detects specified terminology, countdown, tab-label, protocol-spacing, and path translation issues. Regression tests cover Spanish, Chinese, French, and Japanese cases.

SQLite time-format hydration

Layer / File(s) Summary
Startup time-format hydration
src/renderer/App.tsx, src/renderer/stores/timeFormatStore.test.ts
Startup reads SQLite settings and applies explicit 12-hour or 24-hour values. Tests cover enabling and clearing stale state.

MeshCore BLE ghost-node suppression

Layer / File(s) Summary
BLE MAC validation and resolution
src/renderer/lib/connectedMeshcoreBleMac.ts, src/renderer/lib/connectedMeshcoreBleMac.test.ts
The utility stores valid MAC addresses and skips opaque identifiers when resolving suppression candidates.
Connection and reconnect wiring
src/renderer/runtime/useMeshcoreRuntime.ts, src/renderer/runtime/useMeshcoreRuntime.reconnect.test.ts
Initial connections and reconnects derive the suppression MAC through the shared resolver while retaining separate peripheral identity handling.
Meshtastic event suppression
src/renderer/lib/drivers/PacketRouter.ts, src/renderer/lib/meshtastic/meshtasticNodeSideEffects.ts, src/renderer/lib/drivers/PacketRouter.test.ts, src/renderer/lib/meshtastic/meshtasticNodeSideEffects.test.ts
Matching MeshCore ghost-node events no longer update stores, notify listeners, persist records, or trigger RF and telemetry side effects.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the three main changes: ghost-node suppression, 24-hour clock hydration, and localization accuracy fixes.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch update

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.

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

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
scripts/check-i18n-quality.mjs-3828-3834 (1)

3828-3834: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add regression coverage for the Spanish Path rule.

This branch is independent from the four added test cases. Add a Spanish networkPanel.reticulumStackSettings.pathMediumPreference case that contains English Path. This prevents removal or breakage of this validation.

Proposed test
+  it('flags untranslated Path in Spanish path preference', () => {
+    const issues = localeStringQualityIssues({
+      locale: 'es',
+      flatKey: 'networkPanel.reticulumStackSettings.pathMediumPreference',
+      enVal: 'Path preference',
+      val: 'Preferencia de Path',
+    });
+    expectIssue(issues, 'must not leave English "Path"');
+  });

As per path instructions, “include regression tests for ... localization checks.”

🤖 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 `@scripts/check-i18n-quality.mjs` around lines 3828 - 3834, Add an independent
regression fixture in the i18n quality checks for Spanish key
networkPanel.reticulumStackSettings.pathMediumPreference whose value contains
the English word “Path”, and assert that the validator reports an issue. Keep
the existing validation branch unchanged and ensure the test specifically
exercises the locale/key/value condition.

Source: Path instructions

src/renderer/lib/drivers/PacketRouter.test.ts-411-455 (1)

411-455: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Move BLE MAC cleanup into afterEach to avoid test pollution on failure.

resetConnectedMeshcoreBleMacForTests() runs only as the last statement in the test body, after the expect calls. If an expect throws, cleanup is skipped, and the suppression MAC set at line 436 stays applied for later tests. Move the reset to afterEach so it always runs.

🧹 Proposed fix
   it('skips Meshtastic node_info store writes for MeshCore BLE MAC ghost nodes', async () => {
     const { setConnectedMeshcoreBleMac, resetConnectedMeshcoreBleMacForTests } =
       await import('../connectedMeshcoreBleMac');
+    afterEach(() => {
+      resetConnectedMeshcoreBleMacForTests();
+    });
     addIdentity({
       ...
     });
     ...
     expect(useNodeStore.getState().nodes[ID_MT][ghostId].lastHeardAt).toBe(priorHeard);
     expect(listener).not.toHaveBeenCalled();
     detach();
-    resetConnectedMeshcoreBleMacForTests();
   });

Note: afterEach must be registered outside the it callback (e.g., in a wrapping describe or at file scope) for it to apply to this test; the snippet above illustrates intent only.

🤖 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/renderer/lib/drivers/PacketRouter.test.ts` around lines 411 - 455, Move
resetConnectedMeshcoreBleMacForTests cleanup out of the individual test and
register it in an afterEach hook at describe or file scope so it runs even when
assertions fail. Remove the inline reset call from the test while preserving the
existing setConnectedMeshcoreBleMac setup and test behavior.

Source: Path instructions

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

Other comments:
In `@scripts/check-i18n-quality.mjs`:
- Around line 3828-3834: Add an independent regression fixture in the i18n
quality checks for Spanish key
networkPanel.reticulumStackSettings.pathMediumPreference whose value contains
the English word “Path”, and assert that the validator reports an issue. Keep
the existing validation branch unchanged and ensure the test specifically
exercises the locale/key/value condition.

In `@src/renderer/lib/drivers/PacketRouter.test.ts`:
- Around line 411-455: Move resetConnectedMeshcoreBleMacForTests cleanup out of
the individual test and register it in an afterEach hook at describe or file
scope so it runs even when assertions fail. Remove the inline reset call from
the test while preserving the existing setConnectedMeshcoreBleMac setup and test
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: b5468d29-f993-49c7-8b62-c01bf42fe16f

📥 Commits

Reviewing files that changed from the base of the PR and between 0b47a9a and 2837cdd.

⛔ Files ignored due to path filters (16)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/pnpm-lock.yaml
  • src/renderer/locales/cs/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/de/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/es/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/fr/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/id/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/it/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ja/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ko/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/nl/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/pl/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/pt-BR/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/ru/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/tr/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/uk/translation.json is excluded by !src/renderer/locales/**
  • src/renderer/locales/zh/translation.json is excluded by !src/renderer/locales/**
📒 Files selected for processing (12)
  • scripts/check-i18n-quality.mjs
  • scripts/check-i18n-quality.test.mjs
  • src/renderer/App.tsx
  • src/renderer/lib/connectedMeshcoreBleMac.test.ts
  • src/renderer/lib/connectedMeshcoreBleMac.ts
  • src/renderer/lib/drivers/PacketRouter.test.ts
  • src/renderer/lib/drivers/PacketRouter.ts
  • src/renderer/lib/meshtastic/meshtasticNodeSideEffects.test.ts
  • src/renderer/lib/meshtastic/meshtasticNodeSideEffects.ts
  • src/renderer/runtime/useMeshcoreRuntime.reconnect.test.ts
  • src/renderer/runtime/useMeshcoreRuntime.ts
  • src/renderer/stores/timeFormatStore.test.ts

Add an independent i18n-quality fixture for es pathMediumPreference with
English "Path", and move MeshCore BLE MAC test cleanup into afterEach so
it still runs when assertions fail.
@rinchen
rinchen merged commit 2855216 into main Aug 3, 2026
12 checks passed
@rinchen
rinchen deleted the update branch August 3, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant