learning_ai_notes/docs/MOBILE_DELEGATION_ROADMAP.md

12 KiB
Raw Blame History

NoteLett Mobile — Delegation Roadmap (single-agent, sequential)

Purpose: One document to hand to an AI or human implementer. Execute blocks in order (later blocks assume earlier ones are merged). When a block is done, update docs/AGENT_TASK_ROADMAP.md (e.g. Current State table and any new mobile checklist rows), then commit and push.

Canonical product checklist: AGENT_TASK_ROADMAP.md.

Repo: learning_ai_notes
Mobile app root: mobile/ (Expo Router under mobile/src/app/).
Stack: Expo ~55, React Native ~0.83, Zustand + MMKV, @bytelyst/* (auth-client, api-client, telemetry-client, feature-flag-client, kill-switch-client, blob-client, offline-queue, diagnostics-client).

Related pattern: NomGap uses the same idea under learning_ai_fastgap/docs/MOBILE_DELEGATION_ROADMAP.mddo not copy fasting-specific paths or M-numbers; this file is authoritative for NoteLett.


0 — Prerequisites (before writing code)

  • Install: From learning_ai_notes root: pnpm install (workspace: backend, web, mobile).
  • Private registry: If .npmrc references ${GITEA_NPM_HOST}, set env so installs resolve @bytelyst/*.
  • Baseline: cd mobile && pnpm run typecheck (and pnpm test) pass on your machine.
  • Branch: git checkout -b feat/mobile-<block-name> (one branch per major block is fine).

Note: This repos pnpm-workspace.yaml lists only backend, web, mobile — not learning_ai_common_plat. Platform packages typically resolve from the registry; link local plat only if your team uses that workflow.


1 — Already shipped (verify before redoing)

Area What to verify
Router + shell mobile/src/app/_layout.tsx — bootstraps auth, initPlatform(), hydrates stores
Entry mobile/src/app/index.tsxRedirect to /auth
Auth UI mobile/src/app/auth.tsx — email/password → useAuthStore/(tabs)
Auth + API mobile/src/api/auth.ts (createAuthClient, MMKV storagePrefix: PRODUCT_ID), mobile/src/api/client.ts (createApiClient + getToken)
Platform clients mobile/src/lib/platform.ts — telemetry init + trackEvent, feature flags, kill switch, blobClient, diagnostics singleton
Stores + API modules auth-store, notes-store, workspace-store, inbox-store; mobile/src/api/notes.ts, workspaces.ts, note-agent-actions.ts
Offline queue (module) mobile/src/lib/offline-queue.ts exports noteOfflineQueueUI/store wiring is still partial (see capture screen copy)
Tabs + detail (tabs)/ index, search, capture, inbox; mobile/src/app/note/[id].tsx
Tests Vitest on stores (*.test.ts); no @testing-library/react-native in mobile/package.json today

2 — Execution order (mandatory)

Block A  →  Auth flow + session UX (register, refresh, guarded entry)
Block B  →  Kill switch gate + safe degraded UI
Block C  →  Broadcast + survey (web parity)
Block D  →  Profile / settings + feedback-client
Block E  →  Offline queue: enqueue + flush on boot / resume
Block F  →  Blob / attachments (capture or note detail) via shared blobClient
Block G  →  Code health (telemetry versions, a11y, dead code)
Block H  →  RNTL + smoke screen tests
Block I  →  Optional — @bytelyst/sync or deeper sync (last; needs API contract review)

Block A — Auth flow and session UX

A.1 Goals

  • Signed-in users should not be forced through /auth on every cold start — index should redirect to /(tabs) when useAuthStore / getAuthClient() is authenticated (after bootstrap resolves).
  • Add register (and optional forgot-password) paths aligned with backend + web, or document why mobile is sign-in only.
  • Ensure token refresh behavior matches @bytelyst/auth-client expectations (no silent 401 loops on getApiClient()).

A.2 Files to read first

  • mobile/src/app/index.tsx, mobile/src/app/auth.tsx, mobile/src/app/_layout.tsx
  • mobile/src/store/auth-store.ts, mobile/src/api/auth.ts, mobile/src/api/config.ts
  • Web reference: web/src/lib/auth.ts, auth pages under web/src/app/(auth)/

A.3 Optional (platform SDK parity)

If the team standardizes on @bytelyst/react-native-platform-sdk: either integrate AuthProvider with the same MMKV keys as createAuthClient({ storagePrefix: PRODUCT_ID }), or document a minimal bridge (same approach as NomGap Block A in learning_ai_fastgap).

A.4 Done criteria

  • Cold start: authed → tabs; unauthed → auth
  • cd mobile && pnpm run typecheck && pnpm test
  • Update Current State / any new checklist rows in AGENT_TASK_ROADMAP.md
  • Commit: ae0a481feat(mobile): complete block A auth session flow

Block B — Kill switch gate

B.1 Goal

Mirror web middleware / layout behavior: when checkKillSwitch() reports disabled, block main app UI and show message (reuse pattern from web or NomGap KillSwitchGate).

B.2 Files

  • mobile/src/lib/platform.ts (checkKillSwitch)
  • mobile/src/app/_layout.tsx or a small KillSwitchGate wrapper component

B.3 Done criteria

  • Manual test with kill switch on/off (or mocked)
  • Update AGENT_TASK_ROADMAP.md
  • Commit: acdedbcfeat(mobile): add kill switch gate in root layout

Block C — Broadcast + survey (web parity)

C.1 Goal

Integrate @bytelyst/broadcast-client and @bytelyst/survey-client in the root layout (banner + modal), matching API usage from web (see web app layout and @bytelyst/broadcast-client / @bytelyst/survey-client exports).

C.2 Files

  • Add deps to mobile/package.json if missing
  • mobile/src/app/_layout.tsx + new thin components under mobile/src/components/ as needed
  • Reference: web/src/app/(app)/layout.tsx (or wherever BroadcastBanner / SurveyBanner live)

C.3 Done criteria

  • No duplicate/wrong client API (align with current package exports)
  • Update AGENT_TASK_ROADMAP.md
  • Commit: 48896abfeat(mobile): integrate broadcast and survey clients

Block D — Settings / profile + feedback

D.1 Goal

Add @bytelyst/feedback-client from mobile — same payload shape as web (submit({ type, title, body }) or current API).

D.2 Files

  • New screen or tab entry: e.g. mobile/src/app/settings.tsx or profile section on a tab
  • mobile/package.json if adding feedback-client

D.3 Done criteria


Block E — Offline queue wiring

E.1 Goal

noteOfflineQueue exists but capture screen still says wiring is deferred. Enqueue failed note mutations; flush on app start and on connectivity / AppState active (match web offline-queue behavior).

E.2 Files

  • mobile/src/lib/offline-queue.ts
  • mobile/src/store/notes-store.ts (and any create/update paths)
  • mobile/src/app/(tabs)/capture.tsx

E.3 Done criteria

  • Airplane-mode manual test: queue → reconnect → drain
  • Update AGENT_TASK_ROADMAP.md
  • Commit: 5d82160feat(mobile): wire offline queue enqueue and flush

Block F — Blob / attachments

F.1 Goal

Any mobile upload path (future file capture, artifacts) should use blobClient from mobile/src/lib/platform.ts — no second SAS or raw fetch duplicate.

F.2 Files

  • mobile/src/lib/platform.ts (blobClient)
  • Future: note detail or capture file picker

F.3 Done criteria

  • Single upload abstraction; E2E or manual upload test
  • Update AGENT_TASK_ROADMAP.md
  • Commit: feat(mobile): blob uploads via shared blobClient (or refactor if replacing duplicate code)

Block G — Code health

Execute in flexible order; prefer small commits.

Task Hints
Telemetry metadata Use expo-constants for appVersion / buildNumber instead of hardcoded strings in platform.ts
Feature flags in UI Gate experimental mobile surfaces with isFeatureEnabled where web uses flags
Accessibility accessibilityLabel on tab icons and primary actions
Theme Prefer shared tokens from @bytelyst/design-tokens / theme/ consistently

Done criteria

  • Runtime telemetry/client metadata uses expo-constants + platform metadata helpers
  • Accessibility labels added on tabs and primary action buttons
  • Typecheck/tests pass and changes reflected in AGENT_TASK_ROADMAP.md
  • Commit: e4683adfix(mobile): complete block G metadata and accessibility

Block H — RNTL + smoke tests

H.1 Infrastructure

  • Add @testing-library/react-native + @types/react-test-renderer to mobile devDependencies
  • Extend mobile/vitest.config.ts with resolve aliases for RN / Expo / RNTL mocks
  • Create mobile/__mocks__/ with mocks for react-native, expo-router, expo-constants, expo-status-bar, react-native-mmkv, @testing-library/react-native

H.2 Minimum tests

  • Auth screen — import smoke test (valid component, named export, no redirect when unauthenticated)
  • Home tab screen — import smoke test (valid component, named export)

H.3 Done criteria

  • cd mobile && pnpm run typecheck && pnpm test — 32 tests pass (27 store + 5 component)
  • Update AGENT_TASK_ROADMAP.md
  • Commit: 5a0175ffeat(mobile): add Block H — Vitest RN mock aliases + component smoke tests

TODO-1: Deeper RNTL render tests (text assertions, fireEvent) require react-test-renderer to produce non-null output for mocked RN host components in Node. Current smoke tests verify import + isValidElement instead. A future iteration could add jsdom environment + @testing-library/react as an alternative rendering path for full DOM-based assertions.


Block I — Optional sync engine (@bytelyst/sync)

Last. Mobile currently hydrates via REST + Zustand. Replacing with @bytelyst/sync requires mapping entities (notes, workspaces, inbox) to backend contracts and conflict rules — verify with backend before swapping.

I.1 Done criteria (only if attempted)

  • Parity with current hydration + offline behavior
  • Update AGENT_TASK_ROADMAP.md
  • Commit: feat(mobile): adopt @bytelyst/sync (large; may split)

3 — After every block

  1. cd mobile && pnpm run typecheck
  2. cd mobile && pnpm test
  3. Sync AGENT_TASK_ROADMAP.md
  4. Commit with a clear message; push to remote
  5. If block descriptions drift, update this file in the same PR

4 — Reference paths

Area Path
Root layout mobile/src/app/_layout.tsx
Auth mobile/src/app/auth.tsx, mobile/src/store/auth-store.ts
Platform init mobile/src/lib/platform.ts
API mobile/src/api/client.ts, mobile/src/api/config.ts
Workspace definition pnpm-workspace.yaml

End of delegation roadmap. Point your agent at: docs/MOBILE_DELEGATION_ROADMAP.md.