opencode/packages/mobile-voice/AGENTS.md

8.3 KiB

mobile-voice Agent Guide

This file defines package-specific guidance for agents working in packages/mobile-voice.

Scope And Precedence

  • Follow root AGENTS.md first.
  • This file overrides root guidance for this package when rules conflict.
  • If additional local guides are added later, treat the closest guide as highest priority.

Project Overview

  • Expo + React Native app for voice dictation and OpenCode session monitoring.
  • Uses native/device-heavy modules such as whisper.rn, react-native-audio-api, expo-notifications, and expo-camera.
  • Development builds are required for native module changes.

Commands

Run all commands from packages/mobile-voice.

  • Install deps: bun install
  • Start Metro: bun run start
  • Start dev client server (recommended): bunx expo start --dev-client --clear --host lan
  • iOS run: bun run ios
  • Android run: bun run android
  • Lint: bun run lint
  • Typecheck: bun run typecheck
  • Expo doctor: bunx expo-doctor
  • Dependency compatibility check: bunx expo install --check
  • Export bundle smoke test: bunx expo export --platform ios --clear

Build / Verification Expectations

  • For JS-only changes: run bun run lint and verify app behavior via dev client.
  • For TS-heavy refactors: run bun run typecheck in addition to lint.
  • For native dependency/config/plugin changes: rebuild dev client via EAS before validation.
  • If notifications, camera, microphone, or audio-session behavior changes, verify on a physical iOS device.
  • Do not claim a fix unless you validated in Metro logs and app runtime behavior.

Single-Test Guidance

  • This package currently has no dedicated unit test script.
  • Use targeted validation commands instead:
    • bun run lint
    • bun run typecheck
    • bunx expo export --platform ios --clear
    • manual runtime test in dev client

Architecture Priorities

  • Keep screens focused on composition and orchestration. Once a screen owns multiple workflows, extract hooks/components before adding more local state.
  • Prefer extracting pure helpers and config objects before introducing new stores or abstractions.
  • Treat src/app/index.tsx as a composition root, not as the permanent home for onboarding, dictation, monitoring, pairing, persistence, and all UI details.
  • Avoid mirrored state + ref pairs unless they are needed for imperative native APIs, race cancellation, or subscription callbacks.

Code Style And Patterns

Formatting / Structure

  • Preserve existing style (semi: false, concise JSX, stable import grouping).
  • Keep UI changes localized and behavior-preserving; avoid unrelated formatting churn.
  • Prefer feature-adjacent hooks/components over growing a single screen file.

React State / Effects

  • Effects are for subscriptions, timers, persistence, network I/O, and native bridge setup/cleanup.
  • Do not add useEffect just to derive render data from props or state. Derive during render instead.
  • Prefer one source of truth. If a value can be computed from existing state, do not store it separately.
  • Use useMemo only when computation is expensive or stable identity actually matters.
  • Use useCallback only when stable function identity matters for dependencies, cleanup, or memoized children.
  • When UI branches are driven by a small finite state, prefer config tables/objects over long nested ternaries.

Types

  • Avoid any; prefer local type aliases for component state and network payloads.
  • Keep exported/shared boundaries typed explicitly.
  • Parse persisted and network payloads as unknown first, then validate before use.
  • Use discriminated unions for UI modes/status where practical.

Naming

  • Prefer short, readable names consistent with nearby code.
  • Keep naming aligned with existing app state keys (monitorStatus, activeSessionId, etc.).

Error Handling / Logging

  • Fail gracefully in UI (alerts, disabled actions, fallback text).
  • Avoid bare catch {} or .catch(() => {}) for meaningful work. If failure is intentionally best-effort, leave a short comment or use a helper that makes that explicit.
  • Log actionable diagnostics for runtime workflows such as server health checks, relay registration, and notification token lifecycle.
  • Never log secrets or full APNs tokens.
  • Keep hot-path logging behind __DEV__ when possible.

Network / Relay Integration

  • Normalize and validate URLs before storing server configs.
  • Use AbortController or request IDs for overlapping requests, streams, and polling.
  • Keep relay registration idempotent.
  • Guard duplicate scan/add flows to avoid repeated server entries.

Notifications / APNs

  • This package currently assumes APNs relay registration uses the production environment only. Do not add environment switching unless explicitly requested.
  • On registration changes, ensure old token unregister flow remains intact.
  • Treat permission failures as non-fatal and degrade to foreground monitoring when needed.

Performance / RN

  • Validate performance-sensitive changes in a dev client or release build, not only Metro dev mode.
  • During recording and monitoring flows, keep JS-thread work light.
  • Prefer Reanimated/native-thread-friendly animations for motion.
  • For small menus a ScrollView is fine; if a list grows beyond a small bounded menu, move to FlatList or FlashList.

Lint / Quality Bar

  • Keep hooks lint warnings clean before finishing.
  • Treat any, no-console, complexity, and max-lines warnings as refactor prompts, not noise to suppress.
  • Do not disable React Hooks lint rules inline unless there is a documented native-interop reason.
  • When introducing new persistence or network payloads, add or reuse a parser instead of scattering casts.

Native-Module Safety

  • If adding a native module, ensure it is in package.json with an SDK-compatible version.
  • Rebuild the dev client after native module additions or changes.
  • For optional native capability usage, prefer runtime fallback paths instead of hard crashes.

Expo Native Config (EAS)

  • Treat packages/mobile-voice/app.json as the source of truth for iOS native metadata in EAS cloud builds.
  • Do not rely on manual edits in ios/mobilevoice/Info.plist, entitlements files, or PrivacyInfo.xcprivacy; for this package they are generated outputs.
  • Keep generated native folders untracked in git (/ios, /android) to avoid mixed CNG/bare behavior during EAS builds.
  • Put App Store compliance and permission metadata in app config using these fields:
    • expo.ios.infoPlist for Info.plist keys (usage strings, ATS, Bonjour, and related keys).
    • expo.ios.config.usesNonExemptEncryption for export-compliance encryption declaration.
    • expo.ios.entitlements for iOS entitlements.
    • expo.ios.privacyManifests for Apple privacy manifest declarations.
  • Keep app.json entries explicit and review-friendly:
    • Permission descriptions should be complete, product-specific sentences.
    • Compliance keys should be set intentionally rather than relying on implicit defaults.
    • Preserve existing JSON style in this package (concise arrays and stable key grouping).
  • After native config changes, verify resolved config with bunx expo config --type prebuild --json and check the resulting ios fields.

Example shape:

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "...",
        "NSMicrophoneUsageDescription": "..."
      },
      "config": {
        "usesNonExemptEncryption": false
      },
      "entitlements": {
        "com.apple.developer.kernel.extended-virtual-addressing": true
      },
      "privacyManifests": {
        "NSPrivacyAccessedAPITypes": []
      }
    }
  }
}

Common Pitfalls

  • Black screen + "No script URL provided" often means a stale dev client binary.
  • expo-doctor duplicate module warnings may appear in Bun workspaces; prioritize runtime verification.
  • expo lint may auto-generate eslint.config.js; do not commit accidental generated config unless requested.

Before Finishing

  • Run bun run lint.

  • If behavior could break startup, run bunx expo export --platform ios --clear.

  • Confirm no accidental config side effects were introduced.

  • Summarize what was verified on-device vs only in tooling.

  • Dev build (internal/dev client):

    • bunx eas build --profile development --platform ios
  • Production build + auto-submit:

    • bunx eas build --profile production --platform ios --auto-submit