martin-hausleitner/sonar-skills/pairing-diagnose

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Diagnose Sonar pairing failures between two iPhones — QR-scan path silent, Tailscale shown connected but inactive, peer never goes online, distance ring flickering. Use when the user reports "they don't see each other", "QR-scan does nothing", "Tailscale is green but no audio", or any pairing-related bug. Walks through the four connection paths (AWDL → BLE → Tailscale → Internet) and isolates the failing one against real symptoms in the current code.

Install

npx vskill@latest install martin-hausleitner/sonar-skills/pairing-diagnose

SKILL.md

pairing-diagnose

Sonar tries four connection paths in parallel, prioritised by latency: AWDL → BLE → Tailscale → LiveKit. Pairing problems almost always come down to one of those paths failing silently while the others either don't apply or are cosmetic. This skill is a decision tree to find the failing one fast.

When to invoke

  • "the other phone doesn't show up"
  • "QR scan does nothing on the receiving side"
  • "Tailscale says connected but Sonar says no peer"
  • "distance ring is flickering / 0 m / wrong"
  • Anything tagged "pairing" or "verbinden" by the user

Step 0 — Establish baseline

Before guessing, get these facts:

  1. Both devices on `main` and same version? Open SideStore → check version. If different, ship a release first (release-sidestore skill).
  2. Which path does the TopBar claim is active? It will say AWDL, BT, Tailscale, or nothing. That's the claimed truth — we'll verify it.
  3. Is the user on real hardware or simulator? The simulator-relay E2E flow is its own world; if both ends are sims, jump straight to scripts/e2e/run-simulator-e2e.sh and skip this tree.

Decision tree

A. QR-scan side never reacts

Symptom: side B scans the QR shown by side A, dialog appears or doesn't, but B never marks A online.

Anchor files:

  • sonar/UI/PairingView.swift — QR rendering and scanner.
  • sonar/Core/Pairing/PairingToken.swift — decode path; rejects unknown v != currentVersion.
  • sonar/Core/Pairing/PairingService.swift — token acceptance.

Check:

  1. Decode actually succeeded — log line PairingToken.decode returns nil if base64url is corrupt or schema version mismatched. Two devices on different builds = guaranteed silent failure.
  2. appState.pendingPairing is set after scan. If yes but no peer comes online, the token decoded but no transport could act on it — go to B/C/D.
  3. Known issue (open): scan-receive flow has been flaky in v0.2.7. See project_open_issues.md. Treat any scan-side stall as a P0 bug, not a config problem.
B. AWDL path silent (no _sonar._tcp discovery)

Symptom: TopBar shows nothing or only BT, both phones are physically close, same WiFi.

Anchor: sonar/Core/Transport/NearTransport.swift.

Check:

  1. Both phones on WiFi enabled, even if no internet — AWDL needs the WiFi radio. WiFi-off + Hotspot-on is not the same.
  2. Same AWDL mesh — if one phone is on a corporate WiFi with client isolation, AWDL won't bridge. Toggle WiFi off/on on both.
  3. Bonjour service registers — search logs for _sonar._tcp. Absent = NetService failed to publish, usually a permission prompt that was dismissed.
C. Tailscale shows green but no path active

Symptom: Tailscale app says Connected, both phones in same tailnet, but TopBar doesn't show Tailscale.

Anchor files:

  • sonar/Core/Pairing/PairingTokenGenerator.swift:33 — tailscaleIP() populates tsIP.
  • sonar/Core/Transport/TailscaleTransport.swift:75 — applyPairingToken no-ops if tsIP is empty.

Known issue (open): the token's tsIP is frequently empty even when Tailscale is up. Confirm with: paste the QR token's base64 into a decoder and check tsIP. If empty:

  1. Verify the device actually has a 100.x.x.x IP via getifaddrs (LSP/network inspector, or check Tailscale app).
  2. PairingTokenGenerator.tailscaleIP() only finds it if the utun interface is up at token-generation time. Re-generate the QR (the regenerate button in PairingView) after Tailscale is fully connected.
  3. Both phones must be in the same tailnet — the classic trap is logging in with Google on one and GitHub on the other, which silently splits them. See docs/connection-guide.md §3.4.
D. BLE-only path

Symptom: only path that works is BLE; you'd expect AWDL or Tailscale to be primary but they aren't.

Usually a consequence of A/B/C failing, not a root cause. If user complains about quality, that's because BLE is ~30 ms latency + ~50 kBit/s — Opus runs at 16 kBit/s on BLE. Don't blame audio code; surface the upstream path failure.

E. Distance ring flickers / wrong distance

Anchor: NIDiscoveryToken exchange in docs/connection-guide.md §2 ("NIDiscoveryToken-Austausch"), RSSIFallback for non-UWB devices.

Known issue (open): distance-ring stroke flicker is a known cosmetic bug. If the user is asking about the underlying distance value being wrong (not just visual flicker):

  1. Both phones have U1/U2 chip? iPhone 11+ for U1, iPhone 15 Pro+ for U2. Without UWB, fallback is RSSI → less accurate by design.
  2. NIDiscoveryToken bytes — the wire format is [0x02][len:2B][NSSecureCoding payload]. Truncation here gives garbage distances.

Output to user

When done, summarise:

  • Which path is actually working (verified, not what the UI claims).
  • Which path is failing and why (one of A–E, with the specific anchor file).
  • Whether it's a config problem (user fixes it) or a known bug (we fix it).

Do not recommend "restart the app" unless you've ruled out the above. That's the lazy answer.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/martin-hausleitner/sonar-skills/pairing-diagnose/badge)](https://verified-skill.com/skills/martin-hausleitner/sonar-skills/pairing-diagnose)

Something wrong with this skill or its page? Tell us.