learning_ai_notes/docs/MOBILE_DELEGATION_ROADMAP.md
2026-03-30 23:58:37 -07:00

252 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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`](./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.md`**do 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.tsx``Redirect` 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 `noteOfflineQueue`**UI/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
- [x] Cold start: authed → tabs; unauthed → auth
- [x] `cd mobile && pnpm run typecheck && pnpm test`
- [x] Update **Current State** / any new checklist rows in [`AGENT_TASK_ROADMAP.md`](./AGENT_TASK_ROADMAP.md)
- [x] Commit: [`ae0a481`](https://github.com/saravanakumardb1/learning_ai_notes/commit/ae0a481) — `feat(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
- [x] Manual test with kill switch on/off (or mocked)
- [x] Update [`AGENT_TASK_ROADMAP.md`](./AGENT_TASK_ROADMAP.md)
- [x] Commit: [`acdedbc`](https://github.com/saravanakumardb1/learning_ai_notes/commit/acdedbc) — `feat(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`](./AGENT_TASK_ROADMAP.md)
- [ ] Commit: `feat(mobile): 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
- [ ] Graceful offline / error handling
- [ ] Update [`AGENT_TASK_ROADMAP.md`](./AGENT_TASK_ROADMAP.md)
- [ ] Commit: `feat(mobile): feedback client in settings`
---
## 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`](./AGENT_TASK_ROADMAP.md)
- [ ] Commit: `feat(mobile): 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`](./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:** typecheck + tests; reflect changes in [`AGENT_TASK_ROADMAP.md`](./AGENT_TASK_ROADMAP.md).
---
## Block H — RNTL + smoke tests
### H.1 Infrastructure
- [ ] Add **`@testing-library/react-native`** to `mobile` `devDependencies`
- [ ] Extend `mobile/vitest.config.ts` for component tests + any RN mocks
### H.2 Minimum tests
- [ ] **Auth screen** — submit / error path (mock store or API)
- [ ] **One tab screen** — render with mocked stores
### H.3 Done criteria
- [ ] `cd mobile && pnpm test`
- [ ] Update [`AGENT_TASK_ROADMAP.md`](./AGENT_TASK_ROADMAP.md)
- [ ] Commit: `test(mobile): RNTL setup and smoke tests`
---
## 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`](./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`](./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`**.