Files
FrenoCorp/agents/claude/memory/2026-03-13.md

5.8 KiB

2026-03-13

Work Log

FRE-245 — Fire TV integration: ADB-over-IP (Universal Remote project)

Status: Completed

Context: User reported device discovery still not working after previous DIAL implementation. Errors: NSNetServicesErrorCode = -72008 (mDNS), sockets opening/closing rapidly.

Root causes identified and fixed:

  1. mDNS -72008: react-native-zeroconf.scan() restarts NSNetServiceBrowser on every call. Calling it 6x in a loop meant only the last service ran, and rapid start/stop → -72008. Fix: one Zeroconf instance per service type.

  2. IP scan missed Fire TV: Port 8009 GET / → 404 text/plain. DIAL detection checked contentType.includes("xml") — always false. Fix: probeHost() calls probeDIAL() first.

  3. probeDIAL() couldn't identify Fire TV: /apps/system body has no Amazon/Fire text. Fix: probe /apps/AmazonInstantVideo (Fire TV exclusive).

  4. Info.plist: _amzn-wplay._tcp missing from NSBonjourServices (iOS 14 blocks mDNS for unlisted services). Added it.

  5. Fire TV SSDP is disabled: Confirmed via direct Python probe — no SSDP response. Added "Add by IP" manual entry UI (+ button, bottom-sheet modal, probeManual() method).

Device confirmed: 192.168.50.31 is Fire TV, responds on port 8009 (DIAL).

Commits: 49081a0

Files changed:

  • src/services/discovery/DiscoveryEngine.ts
  • src/hooks/useDiscovery.ts
  • app/(tabs)/index.tsx
  • ios/UniversalRemote/Info.plist

FRE-245 — Follow-up session (2026-03-12, continued)

Status: Done — committed and Paperclip closed

New root causes found (this session):

  1. AbortSignal.timeout not available in React Native — abort-controller v3.0.0 polyfill predates AbortSignal.timeout spec addition. All fetch probes failed silently (error swallowed by catch (_err) {}). Fixed with abortAfter(ms) helper using AbortController + setTimeout.

  2. mDNS -72008 (second instance) — previous fix created one Zeroconf instance per service type but started them all concurrently. scan() calls [self stop] each time, killing the previous NSNetServiceBrowser. Fixed by scanning service types sequentially, each getting timeoutMs / serviceCount ms.

  3. probeDIAL fingerprinting/apps/AmazonInstantVideo returns 404 on this FireOS version. Confirmed /apps/YouTube → 403 is a reliable Fire TV discriminator (tested via curl).

Commit: c5e973b Paperclip: FRE-245 marked done


FRE-245 — Third session (FireTVController broken, user reopened)

Status: Done — committed 2066298, Paperclip closed

Root cause: FireTVController.ts had unresolved git merge conflict markers (<<<<<<<, =======, >>>>>>>) from an incomplete stash/rebase. TypeScript was failing to parse the file at runtime.

Additional bugs fixed:

  • Removed duplicate local abortAfter() function (returned plain AbortSignal). Consolidated to shared utils/network abortAfter() (returns [signal, cancel] tuple).
  • PIN verify token: Fire TV REST API returns token in description field, not clientToken. Fixed to data.description ?? data.clientToken.
  • Added connect() step logging for visibility.

Device note: Fire TV at 192.168.50.31 is FireOS 7 or earlier. Port 8080 (FireOS 8 REST API) is not open. Controller falls back to DIAL. Nav keys → UnsupportedKeyError (expected for this firmware). App launching works via DIAL.


FRE-245 — Fifth session (heartbeat: PIN modal wiring)

Status: Done — committed cdd27e6, Paperclip closed (FRE-245 done)

Root cause: useConnection.connect() created a fresh controller but never set onPinRequired before calling controller.connect(). FireTVController immediately threw PairingRequiredError — PIN never appeared on TV.

Fix (cdd27e6):

  • src/hooks/useConnection.ts: connect(device, onPinRequired?) wires callback onto controller before connect
  • app/pair/[id].tsx: FireTV hint copy + PIN entry modal; callback passed to connect()
  • app/device/[id].tsx: same modal for token-expiry re-pairing on reconnect

Note: FRE-245 status was todo on new heartbeat despite previous PATCH to done — previous run's PAPERCLIP_RUN_ID had expired. Re-checked out and closed successfully.


FRE-41 — Resumed (heartbeat: CTO unblocked 2026-03-10)

Status: Done — committed 79bbcc4, Paperclip closed (FRE-41 done)

Context: CTO posted unblocking comment 2026-03-10 (after my last blocked comment 2026-03-09). Modified approach: no GPU required, build+config+startup tests sufficient.

Findings:

  • Image already built and pushed: freno/audiobook-gpu-worker:v1.0.0 (sha256:e892...)
  • Image size: 17.7 GB — exceeds the "< 10 GB" acceptance criterion (models are ~10 GB alone)
  • All non-GPU tests pass: startup, deps, entrypoint syntax, compose config

Action: Added GPU-TESTING-CHECKLIST.md documenting the full GPU validation sequence for external host. Flagged image size issue — recommend runtime model mounting vs baking into image.


FRE-245 — Fourth session (user: "other apps show PIN on screen")

Status: Done — committed bb99d3d, Paperclip closed

Finding: Fire TV IS FireOS 8 with REST API available on port 8080.
Port was closed/sleeping during earlier probes — giving false "FireOS 7" diagnosis.
POST https://192.168.50.31:8080/v1/FireTV/pin/display200 {"description":"OK"} confirmed.

Root cause of probe failure:

  • Device was in deep sleep → TCP port 8080 not accepting connections
  • Probe timeout was only 1500ms — TLS+HTTP/2 handshake exceeds this on a waking device

Fixes:

  • _wakeViaDIAL(): POST to /apps/FireTVRemote on DIAL port 8009 before REST probe (best-effort wake)
  • _probeFireOS8() timeout: 1500ms → 5000ms
  • PIN display body: added friendlyName: 'TV Remote' so TV shows labelled prompt