Files
kvitt/PLAN-M7a.md
T
jacobh2 5e1be38364 Plans and start prompts for every milestone; SPEC v0.2
PLAN-<id>.md for U1, U2, M1, M2a, M2b, M2c-dev, M2c-pi, M3, M4, M5, M6,
M7a-M7f, M8, M9, M10, M11, each with the eleven fixed sections, and a
start prompt per plan in prompts/ plus prompts/README.md (dependency
order and parallel waves).

SPEC v0.2: owner answers D-001 (development-first, M2c split into
M2c-dev and M2c-pi, Gitea registry), D-002 (local backups deleted once
on Drive), D-003 (Splitwise CSV format, English and Swedish variants,
category mapping), OQ-1, OQ-2, OQ-4 answered; M1's readings of
ambiguous contract points stated explicitly in §14.3 to §14.5.
HANDOFF §2 lists the plans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:05:34 +02:00

85 lines
9.0 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.
# PLAN-M7a: Feature onboarding
## 1. Goal
Build `:feature:onboarding`: pairing (S-1), the partner profile step (S-2), waiting for the partner (S-3) and device removed (S-18), against the `:core:model` interfaces and `:core:fakes`. Every state of every screen is screenshot-tested in Swedish and English, light and dark.
## 2. Read first
1. `docs/ux/design-spec.md`: tokens, component inventory, and the sections for S-1, S-2, S-3, S-18.
2. `docs/ux/strings.csv` (keys for these screens) and `docs/ux/screens/S-1-*`, `S-2-*`, `S-3-*`, `S-18-*`.
3. SPEC §13.2 Navigation model and §13.3 Screens (rows S-1, S-2, S-3, S-18 and the states paragraph).
4. SPEC §14.2.4 UI contract: `SessionState`, `SessionRepository`, `ProfileRepository`, `InviteRepository`, `ConnectivityRepository`, `OnlineResult`, `User`.
5. SPEC §4 FR-2 Invites and pairing (AC-2.6, AC-2.7, AC-2.8, AC-2.9, AC-2.10), FR-3 AC-3.3, FR-4 AC-4.3, AC-4.5, FR-5 AC-5.1; §8.3 Invite codes (display and normalisation); §14.4.8 (the "Pair this phone again" case).
6. SPEC §6.2 (module table), §9.9 Online-only actions, §11.2 (row M7a), §11.3 (note M7x), §14.7.
7. Files: `android/core/model/**`, `android/core/design/**` (read only), `android/core/fakes/**`, `android/build-logic/**`, `CLAUDE.md` (BUILD AND VERIFY: Screenshots; ARCHITECTURE RULES; ANTI-PATTERNS).
## 3. Already established
- Features depend only on `:core:model`, `:core:design` and `:core:fakes`; `:core:fakes` only in test, screenshot-test and debug-preview configurations, never in a release build. Features never depend on `:data` or `:domain` (§6.2, §11.3, CLAUDE.md Layering).
- Screens consume the `*State` classes through the repository interfaces of §14.2.4; no field may be added except through a contract change (§14.2.4, §14.8).
- Fake scenarios go only in `android/core/fakes/src/main/kotlin/se/hagstedt/kvitt/fakes/<feature>/` (§11.3, §14.7).
- Strings live in the module's `src/main/res/values/strings.xml` and `values-sv/strings.xml` with keys from `docs/ux/strings.csv`; no string outside that file without a decisions entry (§13.4, §14.7, AC-19.1).
- No hard-coded colours, sizes or strings; tokens and shared components come from `:core:design`, which features may not edit (CLAUDE.md, §14.7). Money and dates go through `MoneyFormatter` and `DateFormatter` (§9.8).
- Online-only actions are disabled with "Needs connection" when offline (§9.9); a REST failure shows "Could not reach the server".
- Navigation graph, deep links and Hilt bindings are in `:app` (M8); a feature exposes its screens with navigation callbacks in the form M2b's feature convention fixed (§11.3).
- Layout and visuals follow `docs/ux/design-spec.md`; TalkBack labels as it specifies; 48 dp targets, 200 % font scale reflow (§13.1).
- No placeholder text in previews or screenshots; goldens are committed; open every changed PNG before committing (CLAUDE.md).
- Pairing accepts a server URL (prefilled `https://icehack.asuscomm.com:8443` in release builds) and a 12-character code shown in groups of 4, normalised per §8.3 before sending; release builds accept only `https://`, debug builds also `http://` for `localhost`, `10.0.2.2` and private LAN addresses (AC-2.7, AC-2.8, §8.3).
- Deep links `kvitt://invite?server=…&code=…` and `https://icehack.asuscomm.com:8443/i/<CODE>` open S-1 with both fields filled; parsing the intent is `:app`'s, the screen takes the values (AC-2.6).
- A `partner` pairing continues to S-2 (display name prefilled, optional picture from the photo picker, "You are joining <owner>") before Home (AC-2.10, AC-4.3).
- S-3: until the partner joins, the admin sees "Waiting for your partner" with "Invite partner" (to S-21) and Settings (AC-5.1, §13.3).
- S-18 after `device_revoked`: explanation that access was removed and local data deleted; "Pair again" goes to S-1 (AC-3.3, §13.3).
- `SessionState.Unrecognised` shows S-1 with "Pair this phone again" (§14.4.8).
## 4. Owned paths
From SPEC §14.7, verbatim: `android/feature/onboarding/**` (owner M7a), and from the `android/core/fakes/**` row: "M7x add files only under `fakes/<feature>/`", here `android/core/fakes/src/main/kotlin/se/hagstedt/kvitt/fakes/onboarding/` (§11.3). Catalog entries and module includes may be added (§14.7, `android/gradle/**` row).
Edit nothing outside these paths; a needed change elsewhere is a contract request to the orchestrator.
## 5. Deliverables
- `android/feature/onboarding/build.gradle.kts`: dependencies `:core:model`, `:core:design`; `:core:fakes` for tests and debug only.
- `android/feature/onboarding/src/main/kotlin/se/hagstedt/kvitt/feature/onboarding/**`: S-1, S-2, S-3, S-18 screens and their state holders.
- `android/feature/onboarding/src/main/res/values/strings.xml`, `values-sv/strings.xml`: keys from `docs/ux/strings.csv`.
- `android/core/fakes/src/main/kotlin/se/hagstedt/kvitt/fakes/onboarding/**`: a scenario per state below.
- Screenshot tests and committed goldens for every screen × state × light/dark × sv/en.
- Unit tests for state holders (code normalisation display, URL rules, error mapping).
Screens and states. Required states for every screen below (SPEC §13.3): **loaded**, **empty**, **offline** (with pending changes), **loading** (first sync only), **error** (a failed online action), and for lists **long content** (long Swedish names, 7-digit amounts), each where it applies. A state that `docs/ux/design-spec.md` marks not applicable for a screen is skipped and named in the report. Each state is screenshot-tested in light and dark, Swedish and English. Screen-specific states from §13.3 "Must show" are added per screen:
- **S-1 Pairing**: loaded (empty fields; release prefill), prefilled from a deep link, pairing in progress, error `invite_invalid`, error network ("Could not reach the server"), error `rate_limited`, "Pair this phone again" (Unrecognised), invalid URL (release `http://`), offline, long content n/a unless the design spec says otherwise.
- **S-2 Partner profile step**: loaded with prefilled name and initials avatar, with picture chosen, upload in progress, error (failed upload), offline ("Needs connection" for the picture), long Swedish name.
- **S-3 Waiting for partner**: with a pending invite's expiry, without a pending invite, offline, error.
- **S-18 Device removed**: loaded (single state), plus any state the design spec adds.
## 6. Steps
1. Worktree. From the main checkout `/Users/jhag/projects/kvitt`: `git worktree add .claude/worktrees/agent-m7a -b agent-m7a main`, then in `.claude/worktrees/agent-m7a`: `git reset --hard main`. Copy `android/local.properties` from the main checkout (add `sdk.dir=/opt/homebrew/share/android-commandlinetools` if missing; never overwrite or commit). Run `tools/install-git-hooks.sh`.
2. Read §2 in order. Confirm M6 has landed (`android/core/design/` has components on `main`); if not, stop and report.
3. Run `python3 tools/dependency-report/latest.py`; record the lines. No new library is expected; any one added is at its latest stable version from official docs; record it.
4. Write the fake scenarios under `fakes/onboarding/` for every state listed in §5.
5. Write the state holders and screens, one screen at a time, with strings from `docs/ux/strings.csv` in both languages.
6. Write the screenshot tests; record goldens; open every PNG and compare with `docs/ux/screens/`.
7. Run the gate (§7). Commit on `agent-m7a`, `git rebase main`, rerun the gate. Never merge, push or remove the worktree.
## 7. Gate
From SPEC §11.2, verbatim: "Android gate with screenshot tests of every state, sv and en, light and dark".
Command, from `android/`: `PATH=/opt/homebrew/opt/openjdk@25/bin:$PATH ../tools/gradle-serial.sh check`.
Green means: `BUILD SUCCESSFUL` in this session; screenshot verification passes for `:feature:onboarding`; the report lists, per screen, every state × light/dark × sv/en golden; unit tests 0 failures in fresh XML.
## 8. HUMAN steps
From SPEC §11.2, verbatim: "none".
## 9. Out of scope
- Other screens: S-4, S-5, S-6, S-16, S-17 (M7b); S-7, S-8 (M7c); S-9, S-10 (M7d); S-11, S-12 (M7e); S-13 to S-15, S-19 to S-22 (M7f).
- Intent parsing, navigation graph, Hilt, the notification-permission prompt after pairing (AC-2.9), the revoke wipe (M8); the real `SessionRepository` (M5).
- Editing `:core:design` (requests go to the orchestrator) or `:core:model`.
- Fake scenarios outside `fakes/onboarding/`.
## 10. Report
- Branch `agent-m7a`, head commit hash after rebasing on `main`.
- Gate output: BUILD line, actionable tasks line, screenshot task result, test counts from fresh XML.
- Screens × states table with golden file names; states skipped as not applicable.
- Versions added (if any) with sources; dependency-report lines.
- Strings used that are missing from `strings.csv` (should be none) and design-spec mismatches.
- Numbering used or `TODO(spec)` occurrences.
- Contract requests (`:core:design`, `:core:model`), open questions, spec gaps (with section numbers).
## 11. Numbering
Decision ids, spec version and schema version are assigned by the orchestrator in the start prompt; use `TODO(spec)` if none was given.