Refresh miniapp capabilities after pairing - #3687
Conversation
📋 PR Review Helper📱 Mobile App Build✅ Ready to test! (commit 🕶️ ASG Client Build⏳ Waiting for build... 🔀 Test Locallygh pr checkout 3687 |
There was a problem hiding this comment.
1 issue found across 7 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="mobile/src/services/__tests__/localMiniappCapabilities.test.ts">
<violation number="1" location="mobile/src/services/__tests__/localMiniappCapabilities.test.ts:46">
P3: Consider adding coverage for the two remaining behaviors this PR changed: the hasDisplay:false / display.canPosition:false normalization for a display-less wearable, and that CAPABILITIES_UPDATE stops being emitted (unsubscribe) once the last miniapp is unregistered. The current test only exercises the positive display-capable path.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| sent.length = 0 | ||
| setDefaultWearable(DeviceTypes.G2) | ||
|
|
||
| const update = payloads().find((payload) => payload.type === MiniappResponseType.CAPABILITIES_UPDATE) |
There was a problem hiding this comment.
P3: Consider adding coverage for the two remaining behaviors this PR changed: the hasDisplay:false / display.canPosition:false normalization for a display-less wearable, and that CAPABILITIES_UPDATE stops being emitted (unsubscribe) once the last miniapp is unregistered. The current test only exercises the positive display-capable path.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At mobile/src/services/__tests__/localMiniappCapabilities.test.ts, line 46:
<comment>Consider adding coverage for the two remaining behaviors this PR changed: the hasDisplay:false / display.canPosition:false normalization for a display-less wearable, and that CAPABILITIES_UPDATE stops being emitted (unsubscribe) once the last miniapp is unregistered. The current test only exercises the positive display-capable path.</comment>
<file context>
@@ -0,0 +1,65 @@
+ sent.length = 0
+ setDefaultWearable(DeviceTypes.G2)
+
+ const update = payloads().find((payload) => payload.type === MiniappResponseType.CAPABILITIES_UPDATE)
+ expect(update?.capabilities).toMatchObject({
+ modelName: DeviceTypes.G2,
</file context>
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Summary
hasDisplay: falsein Mentra Maps capability normalizationRoot cause
Prod report
rep_01KZA6T034CWQDMHGWGMQ1PZ8Yshows Mentra Maps connecting whiledefault_wearablewas still Simulated Glasses. G2 was promoted about 816 ms after CONNECT, but the local runtime only sent capabilities in CONNECT_ACK and never sent CAPABILITIES_UPDATE. The miniapp therefore kept the simulated/basic display profile even though the phone build already defined G2 withdisplay.canPosition: true.This replaces the compatibility workaround from #3686 with capability lifecycle synchronization; it does not hardcode behavior by model name.
Context: https://mentra-labs.slack.com/archives/C0A8015JBPT/p1785975342337889
Validation
cd miniapps/navigation && bun test— 86 passedcd mobile && bun run test --runInBand src/services/__tests__/localMiniappCapabilities.test.ts src/services/__tests__/localMiniappButtonSubscriptions.test.ts— 2 passedcd mobile && bun run compileFollow-up to #3682 and #3686.
Summary by cubic
Keeps miniapp capabilities in sync with wearable pairing and hardens CONNECT/AUTH flows against races and stale retries, including crash-respawn resets. Fixes Mentra Maps display detection and bundles
com.mentra.navigation1.1.30.Bug Fixes
defaultWearablechanges; stop listening when no apps are connected.hasDisplay: falseas authoritative;canPositionstays off without a display or with a legacy descriptor.Dependencies
com.mentra.navigation-1.1.30.zipand updatebundledMiniapps.ts.Written for commit ff333d4. Summary will update on new commits.
Note
Medium Risk
Changes the local miniapp CONNECT/auth lifecycle and live capability delivery, which affects every miniapp session, but behavior is covered by new focused tests and is narrowly scoped to pairing races and respawn safety.
Overview
Fixes miniapps (notably Mentra Maps) keeping a stale simulated/basic display profile when G2 is promoted shortly after CONNECT.
Local miniapp runtime now resolves CONNECT_ACK capabilities after async auth (not at CONNECT start) and broadcasts
CAPABILITIES_UPDATEto all handshook sessions whendefaultWearablechanges, with the subscription torn down when no apps are connected. Handshake generation invalidates stale async CONNECT completions, initial AUTH retries, and late mints after crash-respawn/resetHandshake.Mentra Maps treats explicit
hasDisplay: falseas authoritative so a legacydisplaydescriptor cannot re-enable HUD positioning. Ships 1.1.30 in the app bundle.Reviewed by Cursor Bugbot for commit ff333d4. Bugbot is set up for automated code reviews on this repo. Configure here.