SPEC v0.3: orchestrator resolutions of the plans' open points
Records D-004 and D-015 to D-025: shells and ownership, server seams (router middleware, rate_limit layer, tasks::start, AuditWriter and PushQueue traits, next_occurrence_date in kvitt-domain, M3 owns recurring generation, M4 lands after M3), OpenAPI parsed-value equality, feature convention and strings, empty fake scenario and resolveRange exception, shared ledger rows and editor fields in :core:design, no bundled font, pruning at 04:00, development infrastructure as M2c-dev built it, M2c-pi allowances, release keystore, production import procedure. Plans and prompts close their open points; HANDOFF rewritten to the real state; CLAUDE.md: implementation agents never edit SPEC.md or docs/decisions.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+12
-10
@@ -7,14 +7,17 @@ Assemble the app: `:app` navigation and deep links, Hilt bindings from the `:cor
|
||||
1. SPEC §6.2 Android app (module table, the paragraph on the architecture check) and §13.2 Navigation model.
|
||||
2. SPEC §14.6 Push payload v1, "Phone handling" (items 1 to 4).
|
||||
3. SPEC §4 FR-2 AC-2.6, AC-2.9, AC-2.10; FR-3 AC-3.3, AC-3.4; FR-5 AC-5.1; FR-13 Push notifications (AC-13.5 to AC-13.8); FR-15 AC-15.3; FR-16 In-app update; §13.3 system notification copy table.
|
||||
4. SPEC §8.2 (token never logged), §8.5 Transport, §8.8 Phone hardening, §10.5.3 (the `kvitt.tls.pinnedRoot` property), §10.6 (version code and name properties, release signing keys), §10.7 (`google-services.json`).
|
||||
4. SPEC §8.2 (token never logged), §8.5 Transport, §8.8 Phone hardening, §10.5.3 (the `kvitt.tls.pinnedRoot` property), §10.6 (version code and name properties, release signing keys), §10.7 (`google-services.json` in `infra/secrets/`, copied by `infra/dev/copy-google-services.sh`).
|
||||
5. SPEC §14.4.8 Epoch recovery and re-pairing (the `Unrecognised` path), §14.2.4 (`SessionState`, `UpdateState`).
|
||||
6. SPEC §10 intro "Development first (D-001)" and `infra/dev/README.md` (how to run and bootstrap the development server).
|
||||
7. SPEC §11.2 (row M8), §11.3 (note M8), §14.7.
|
||||
8. Files: `android/app/**`, `android/build-logic/**`, `android/gradle/libs.versions.toml`, the public APIs of `android/data/**` (its Hilt modules), `android/feature/*/**` (their screen entry points), `android/core/model/**`, `docs/ux/strings.csv` (notification copy), `docs/decisions.md` D-001, `CLAUDE.md` (THE PHONE, THE OWNER, BUILD AND VERIFY).
|
||||
6. SPEC §10 intro "Development first (D-001)" and `infra/README.md` (dev stack section) and the scripts in `infra/dev/` (how to run and bootstrap the development server).
|
||||
7. SPEC §11.2 (row M8), §11.3 (note M8), §14.7, §6.2 "Feature convention (D-017)"; `docs/decisions.md` D-017, D-022.
|
||||
8. Files: `android/app/**`, `android/build-logic/**`, `android/gradle/libs.versions.toml`, the public APIs of `android/data/**` (its Hilt modules), `android/feature/*/**` (their screen entry points), `android/core/model/**`, `docs/ux/strings.csv` (notification copy, which lives in `:core:design`), `docs/decisions.md` D-001, `CLAUDE.md` (THE PHONE, THE OWNER, BUILD AND VERIFY).
|
||||
|
||||
## 3. Already established
|
||||
- Only `:app` sees every module and binds the `:data` repositories to the `:core:model` interfaces through Hilt; features never see `:data` or `:domain` (§6.2, CLAUDE.md Layering). M8 is the only plan that edits `:app` after M2b (§11.3).
|
||||
- Feature convention (D-017): each feature exposes one composable entry point per screen with a `hiltViewModel()`-provided ViewModel and navigation as plain lambdas; `:app` owns the `NavHost` and connects every lambda to a route; fakes are bound only in test and debug-preview source sets.
|
||||
- Strings (D-017): `:app` holds only the app name; the notification copy and the channel name come from `:core:design`'s shared strings.
|
||||
- `google-services.json` is in `infra/secrets/` of the main checkout (M2c-dev, D-022); M8 copies it into `android/app/` (git-ignored) with `infra/dev/copy-google-services.sh`.
|
||||
- Navigation: bottom navigation Home (Översikt), Analytics (Statistik), Settings (Inställningar); FAB "Add expense" on Home and Account detail; account detail, editors, settle up, details and settings sub-screens are pushed screens with back; the expense editor is full screen (§13.2).
|
||||
- Deep links: `kvitt://invite?server=…&code=…` and `https://icehack.asuscomm.com:8443/i/<CODE>` (unverified link) open S-1 with both fields filled (AC-2.6). Only `MainActivity` and the FCM service are exported (§8.8).
|
||||
- After pairing: full sync, then the `POST_NOTIFICATIONS` request (AC-2.9); partner pairing goes through S-2 before Home (AC-2.10).
|
||||
@@ -32,20 +35,20 @@ From SPEC §14.7, verbatim: `android/adapter/fcm/**`, `android/app/**` (after th
|
||||
|
||||
Edit nothing outside these paths; a needed change elsewhere is a contract request to the orchestrator.
|
||||
|
||||
Note: network security config (§8.5), manifest hardening (§8.8) and release signing and version properties (§10.6) are not named in §11.2's M8 row, but they live in `:app`, which only M8 edits (§11.3); they are listed as deliverables here. The orchestrator confirms or reassigns them in the start prompt.
|
||||
Network security config (§8.5), manifest hardening (§8.8), release signing and version properties (§10.6) are M8's (§11.2 row M8, v0.3). Never edit `SPEC.md` or `docs/decisions.md`: put proposed decision entries in the report.
|
||||
|
||||
## 5. Deliverables
|
||||
- `android/app/build.gradle.kts`: dependencies on every module, Hilt, Firebase (via `google-services.json`), version properties, release signing config read from `local.properties`.
|
||||
- `android/app/src/main/AndroidManifest.xml`: `MainActivity` with launcher and deep-link filters, FCM service from `:adapter:fcm`, `POST_NOTIFICATIONS`, `REQUEST_INSTALL_PACKAGES`, backup disabled, data extraction rules.
|
||||
- `android/app/src/main/res/xml/network_security_config.xml` (release) and the debug variant; `data_extraction_rules.xml`.
|
||||
- `android/app/src/main/kotlin/se/hagstedt/kvitt/**`: `Application` (Hilt), `MainActivity`, navigation graph, deep-link parsing, Hilt modules binding interfaces to `:data`, push event handling and notification building, revoke and `Unrecognised` routing, notification-permission request after pairing.
|
||||
- `android/app/src/main/res/values/strings.xml`, `values-sv/strings.xml`: notification copy and channel name from `docs/ux/strings.csv`.
|
||||
- `android/app/src/main/res/values/strings.xml`, `values-sv/strings.xml`: the app name only (from M2b's shell); notification text is built from `:core:design` strings.
|
||||
- `android/adapter/fcm/**`: `FirebaseMessagingService`, token registration, mapping to `PushEvent`, unit tests for the mapping.
|
||||
- Unit tests in `:app`: deep-link parsing, notification text building for each §14.6 type and the generic fallback, notification ids.
|
||||
- An end-to-end run report in the plan report (no file): pairing and the offline test on the phone.
|
||||
|
||||
## 6. Steps
|
||||
1. Worktree. From the main checkout `/Users/jhag/projects/kvitt`: `git worktree add .claude/worktrees/agent-m8 -b agent-m8 main`, then in `.claude/worktrees/agent-m8`: `git reset --hard main`. Copy `android/local.properties` and `android/app/google-services.json` from the main checkout (never commit them; add `sdk.dir` to `local.properties` if missing). Run `tools/install-git-hooks.sh`.
|
||||
1. Worktree. From the main checkout `/Users/jhag/projects/kvitt`: `git worktree add .claude/worktrees/agent-m8 -b agent-m8 main`, then in `.claude/worktrees/agent-m8`: `git reset --hard main`. Copy `android/local.properties` from the main checkout, then run `infra/dev/copy-google-services.sh /Users/jhag/projects/kvitt` to place `android/app/google-services.json` from the main checkout's `infra/secrets/` (never commit either; add `sdk.dir` to `local.properties` if missing). Run `tools/install-git-hooks.sh`.
|
||||
2. Read §2 in order. Confirm M3, M4, M5, M7a to M7f and M2c-dev have landed; if not, stop and report.
|
||||
3. Run `python3 tools/dependency-report/latest.py`; record the lines. Versions: Firebase BoM and the Google services Gradle plugin at latest stable (firebase.google.com release notes); Hilt navigation and Navigation Compose at latest stable; confirm current FCM Android and `PackageInstaller` usage from official docs; record each.
|
||||
4. Hilt modules and the navigation graph; wire every feature screen; deep links.
|
||||
@@ -53,7 +56,7 @@ Note: network security config (§8.5), manifest hardening (§8.8) and release si
|
||||
6. Revoke wipe, `Unrecognised` routing, notification permission after pairing, update banner wiring.
|
||||
7. Manifest hardening, network security configs, version properties, release signing config (no keystore needed for debug).
|
||||
8. Run the gate's build part: `PATH=/opt/homebrew/opt/openjdk@25/bin:$PATH ../tools/gradle-serial.sh check` from `android/`.
|
||||
9. Development server: start it per `infra/dev/README.md` with an image built from current `main` (no Gradle build running while Docker builds), reset its dev data, run `kvitt-server bootstrap`, note the code (never log it to a committed file).
|
||||
9. Development server: start it per `infra/README.md` (dev stack section) and the scripts in `infra/dev/` with an image built from current `main` (no Gradle build running while Docker builds), reset its dev data, run `kvitt-server bootstrap`, note the code (never log it to a committed file).
|
||||
10. Phone (only if the start prompt names this plan as the one on the phone): `/opt/homebrew/share/android-commandlinetools/platform-tools/adb shell pm list packages | grep se.hagstedt.kvitt` to confirm ids; `PATH=/opt/homebrew/opt/openjdk@25/bin:$PATH tools/gradle-serial.sh installDebug`. The debug build must not replace a build holding the owner's real data without asking.
|
||||
11. End-to-end test with the owner (HUMAN, §8): pairing with the bootstrap code and the Mac's LAN URL; the agent then creates a partner invite and accepts it with `curl` as a scripted partner device on the dev server, so the household is complete (FR-5); the owner adds an expense offline, reconnects; the agent confirms the expense reached the server (pull with the scripted partner's token) and pulls the app's sync state over USB (`adb shell run-as se.hagstedt.kvitt.debug …`) to show pending count 0. If push is configured, the agent also posts an expense as the scripted partner and asks the owner whether a notification appeared.
|
||||
12. Commit on `agent-m8`, `git rebase main`, rerun the gate. Never merge, push or remove the worktree.
|
||||
@@ -77,9 +80,8 @@ Where in the flow: step 11, after the debug build is installed and the dev serve
|
||||
- Branch `agent-m8`, head commit hash after rebasing on `main`.
|
||||
- Gate output: BUILD line, actionable tasks line, test counts from fresh XML; the end-to-end result (pair, offline pending, synced, pending count 0), with what the agent checked itself.
|
||||
- Versions chosen with sources; dependency-report lines.
|
||||
- Whether the start prompt confirmed the network security config, hardening and signing deliverables.
|
||||
- Dev server state left behind (running or stopped; scripted partner device name).
|
||||
- Numbering used or `TODO(spec)` occurrences.
|
||||
- Proposed decision entries (never written to `SPEC.md` or `docs/decisions.md` by this agent) or `TODO(spec)` occurrences.
|
||||
- HUMAN steps done and outstanding, worded for relay.
|
||||
- Contract requests, open questions, spec gaps (with section numbers).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user