UX: owner answers round 2: no suggestion caption, most-often history, 14 default categories, finer import mapping

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-18 07:51:05 +02:00
parent 4c1a4b5a9d
commit 4d3c343f16
3 changed files with 132 additions and 77 deletions
+63 -12
View File
@@ -13,10 +13,15 @@ Every entry has: the owner's answer or the finding, the proposed decision text f
| Category from the description | **Yes:** the category is auto-selected from the description and the user can still change it. Rule: history first, then a built-in keyword list, then the AC-8.6 default. The keyword list is learned from the household's Splitwise export. |
| S-1 "Ditt namn" field (partner types the name on S-1 and confirms it on S-2) | **OK** |
| Swedish wording "Ni är kvitt", "Gör upp", "Du lånade ut / Du lånade", "Inte inblandad" | **Yes** |
| Muted Kalas (2026-10-18, second round) | **Approved** ("let's go with that for now"). |
| Mark the suggested category ("Vald utifrån beskrivningen")? | **No:** the category is simply selected; a wrong guess is changed with one tap; simpler UI. |
| History match: most recent or most often? | **Most often.** |
| Import granularity | Splitwise's categories are finer than Kvitt's ten defaults (several "Övrigt" under different groups); map them better. "Hemförsäkring" must not end up in Övrigt. |
| Which new default categories? | **All four proposed:** Boende, Försäkringar, Barn, Avgifter & skatter. |
## UX-1 Direction: Kalas, muted
* **Decision:** the app's visual direction is U1's direction 3 "Kalas" (cards, very round shapes, a solid category-colour tile on every expense, the seesaw balance), with a muted palette (status: being revised; see `directions/3-kalas/`). Typeface per D-020 (Material 3 default, Roboto); Kalas's preview font Nunito is dropped.
* **Decision:** the app's visual direction is U1's direction 3 "Kalas" (cards, very round shapes, a solid category-colour tile on every expense, the seesaw balance), with the muted palette of `directions/3-kalas/` (owner approved 2026-10-18). Typeface per D-020 (Material 3 default, Roboto); Kalas's preview font Nunito is dropped.
* **Why:** owner's pick; muted because bright colours tire over years of daily use.
* **Spec:** none beyond UX-5 (category colours). U2's `design-spec.md` carries the tokens.
@@ -27,22 +32,67 @@ Every entry has: the owner's answer or the finding, the proposed decision text f
## UX-3 Category suggested from the description
* **Decision (owner, 2026-10-18):** for a new expense, the editor selects a category from the description as the user types, while the user has not picked a category by hand in this editor session: (1) history match, (2) built-in keyword list, (3) the AC-8.6 default. The user can always change it. Editing an existing expense never changes its category automatically.
* **Decision (owner, 2026-10-18):** for a new expense, the editor selects a category from the description as the user types, while the user has not picked a category by hand in this editor session: (1) history match, the category used **most often** among matching expenses, (2) built-in keyword list, (3) the AC-8.6 default. The selected category is not marked as a suggestion (no caption); the user changes it with one tap. Editing an existing expense never changes its category automatically.
* **Why:** most expenses repeat the same shops; fewer taps in the ten-second flow (§13.1).
* **Evidence** (chronological replay of the household's 1 775 Splitwise expenses, aggregates only, `category-suggestion.md`): history step right 92.3 % of the time and used for 71.5 % of rows; keyword step 94.2 % on 7.8 %; overall 79.5 % correct versus 31.9 % for today's AC-8.6 default alone. At cold start (no history) keywords fire on 78 % of rows and are right 96 % of the time.
* **Evidence** (chronological replay of the household's 1 775 Splitwise expenses with the 14 categories of UX-8 and the mapping of UX-7, aggregates only, `category-suggestion.md`): history step ("most often") used for 71.5 % of rows and right 92.8 % of the time; keyword step 92.4 % on 8.2 %; overall **79.7 %** correct versus 30.5 % for today's AC-8.6 default alone ("most recent" would give 79.0 %). Cold start (no history): keywords fire on 77 % of rows and are right 96 % of the time.
* **Spec changes:**
* AC-8.6: the category default becomes "the suggestion of §9.11, which falls back to the current rule".
* New §9.11 "Category suggestion": the text CS-1 to CS-7 of `category-suggestion.md`.
* New contract file `contracts/category-keywords.csv` (columns `keyword,match,default_key,source`; draft `docs/ux/category-keywords.csv`, 149 entries), listed in §14.8.
* New contract file `contracts/category-keywords.csv` (columns `keyword,match,default_key,source`; draft `docs/ux/category-keywords.csv`, 148 entries, none mapping to `other`), listed in §14.8.
* §14.2.4: `ExpenseRepository` gains `suspend fun suggestCategory(accountId: AccountId?, description: String): CategoryId?` (computed in `:data` from Room and the keyword table; the editor calls it on description and account changes while the category was not picked by hand).
* §14.5: a pure Kotlin function `suggestCategory(description, history, keywords, activeCategories, fallback)` in `:domain` with test vectors (Kotlin only, like analytics).
* `strings.csv`: `expense_editor_category_suggested` "Vald utifrån beskrivningen" / "Chosen from the description".
* **Open points** (owner, low stakes; defaults in brackets): keep the five keywords that pick Övrigt, e.g. insurance words [keep]; "most recent" vs "most frequent" history match, the latter about one point better [most recent, as chosen].
## UX-7 §10.8 misses nine Swedish Splitwise category names
## UX-7 Finer Splitwise import mapping (§10.8)
* **Finding** (from the export analysis): 21 rows use Swedish Splitwise category names that the §10.8 mapping table lacks: Utbildning (4), Tjänster (3), Livet - Övrigt (3), Kläder (3), Städning (2), Flyg (2), Spel (2), Verktyg - Övrigt (1), Cykel (1). They would import as `other` with a warning.
* **Proposed decision:** add them to the §10.8 table and `server/crates/kvitt-import/data/splitwise_categories.csv` by their English equivalents: Utbildning → other, Tjänster → home, Livet - Övrigt → other, Kläder → shopping, Städning → utilities, Flyg → travel, Spel → entertainment, Verktyg - Övrigt → utilities, Cykel → transport. (Needed by M9.)
* **Finding** (export analysis): 21 rows use Swedish Splitwise category names that the §10.8 table lacks (Utbildning 4, Tjänster 3, Livet - Övrigt 3, Kläder 3, Städning 2, Flyg 2, Spel 2, Verktyg - Övrigt 1, Cykel 1); and §10.8 collapses Splitwise's finer categories, so e.g. Försäkringar (26 rows), Barnomsorg (73) and Skatter (19) land in `other` and Hyra (106) and Avbetalning/Amortering (48) in `home`.
* **Decision (owner, 2026-10-18):** map Splitwise categories as finely as Kvitt's categories allow, with the four new defaults of UX-8.
* **Spec:** the §10.8 table and `server/crates/kvitt-import/data/splitwise_categories.csv` become:
| Splitwise category (English) | Splitwise category (Swedish) | Kvitt `default_key` |
|---|---|---|
| Groceries, Food and drink - Other, Liquor | Livsmedel, Mat och dryck - Övrigt, Alkohol | `groceries` |
| Dining out | Restaurangbesök | `restaurants` |
| Rent, Mortgage | Hyra, Avbetalning/Amortering | `housing` |
| Electronics, Furniture, Household supplies, Maintenance, Services, Pets, Home - Other | Elektronik, Möbler, Förbrukningsvaror, Skötsel/underhåll, Tjänster, Husdjur, Hem - Övrigt | `home` |
| Electricity, Heat/gas, Water, Trash, TV/Phone/Internet, Cleaning, Utilities - Other | El, Värme/gas, Vatten, Sophämtning, TV/telefon/internet, Städning, Verktyg - Övrigt | `utilities` |
| Insurance | Försäkringar | `insurance` |
| Bicycle, Bus/train, Car, Gas/fuel, Parking, Taxi, Transportation - Other | Cykel, Buss/tåg, Bil, Bensin/bränsle, Parkering, Taxi, Transport - Övrigt | `transport` |
| Hotel, Plane | Hotell, Flyg | `travel` |
| Games, Movies, Music, Sports, Entertainment - Other | Spel, Filmer, Musik, Sport, Underhållning - Övrigt | `entertainment` |
| Medical expenses | Sjukvård/medicin | `health` |
| Childcare | Barnomsorg | `children` |
| Clothing, Gifts | Kläder, Presenter | `shopping` |
| Taxes | Skatter | `fees` |
| General, Education, Life - Other, Other | Allmänt, Utbildning, Livet - Övrigt | `other` |
| any other value | any other value | `other`, counted as unmapped |
Swedish names not seen in the export (El, Värme/gas, Vatten, Sophämtning, Husdjur) are Splitwise's Swedish labels by analogy and must be checked against Splitwise before M9 relies on them; an unseen name simply stays unmapped.
## UX-8 Four new default categories
* **Decision (owner, 2026-10-18):** Kvitt seeds 14 default categories instead of 10. New: Boende, Försäkringar, Barn, Avgifter & skatter. Hem keeps furniture, supplies, maintenance, electronics and services; rent and mortgage move to Boende.
* **Why:** the household's history shows these as separate, large groups (Hyra + Amortering 154 rows, Barnomsorg 73, Försäkringar 26, Skatter 19) that were collapsed into Hem and Övrigt; separate categories make analytics and the category suggestion meaningful.
* **Spec (AC-7.2 table, full new list in sort order; new rows in bold):**
| `default_key` | English name | Swedish name | `icon` | `color` | `sort_order` |
|---|---|---|---|---|---|
| `groceries` | Groceries | Mat & hushåll | `shopping_cart` | `green` | 10 |
| `restaurants` | Restaurants | Restaurang & café | `restaurant` | `orange` | 20 |
| **`housing`** | **Housing** | **Boende** | **`key`** | **`indigo`** | **25** |
| `home` | Home | Hem | `home` | `brown` | 30 |
| `utilities` | Utilities | Räkningar | `bolt` | `yellow` | 40 |
| **`insurance`** | **Insurance** | **Försäkringar** | **`shield`** | **new token (UX-5)** | **45** |
| `transport` | Transport | Transport | `directions_car` | `blue` | 50 |
| `travel` | Travel | Resor | `flight` | `teal` | 60 |
| `entertainment` | Entertainment | Nöje | `movie` | `purple` | 70 |
| `health` | Health | Hälsa | `medical_services` | `red` | 80 |
| **`children`** | **Children** | **Barn** | **`child_care`** | **`lime`** | **85** |
| `shopping` | Shopping | Shopping | `shopping_bag` | `pink` | 90 |
| **`fees`** | **Fees & taxes** | **Avgifter & skatter** | **`account_balance`** | **new token (UX-5)** | **95** |
| `other` | Other | Övrigt | `category` | `grey` | 100 |
* **Contract consequences** (one landing, numbered by the docs agent): AC-7.2 table; §9.7 icon set gains `key`, `shield`, `account_balance` (33 tokens) and the colour set gains two tokens (UX-5); §14.1 seed rows with four new fixed ids and a server schema **migration to version 2** inserting them (existing databases, including the development stack, get them on upgrade); `DefaultCategoryKey` and `ColorToken` in §14.2.4 gain the new values and `CategoryIcons.ALL` the new icons; the OpenAPI enums; default-name strings in both languages (`strings.csv`); test vectors that enumerate categories, if any. The Room schema is unchanged (category rows arrive through sync).
* **Order matters for existing milestones:** M3 (server) and M5 (`:data`) already landed with ten defaults, so this is a contract change against code on `main`, not only the spec.
## UX-4 S-1 asks for the display name
@@ -53,7 +103,7 @@ Every entry has: the owner's answer or the finding, the proposed decision text f
## UX-5 Category colour values (§9.7)
* **Finding:** several provisional §9.7 values fail contrast as icon colours on tinted containers (light orange, yellow, lime).
* **Decision:** replace the §9.7 hex values with the muted Kalas values (pending; filled in when the revision is approved). Token names unchanged.
* **Decision:** replace the §9.7 hex values with the muted Kalas values, and add two colour tokens for the new categories of UX-8 (values and names from the Kalas revision in progress; filled in when it reports). Existing token names unchanged.
* **Spec:** §9.7 table values.
## UX-6 Smaller UX rules found during U1 (no owner question needed)
@@ -69,5 +119,6 @@ Every entry has: the owner's answer or the finding, the proposed decision text f
## Status
* U1: delivered (`d27f92e` rebased on `main`), direction picked.
* Done: muted Kalas revision (`directions/3-kalas/`, awaiting the owner's look); keyword list and suggestion analysis (`category-keywords.csv`, `category-suggestion.md`).
* Next: owner approves the muted palette → U2 `design-spec.md`, renamed `strings.csv`, per-screen PNGs, and the final values for UX-3 and UX-5.
* Done: muted Kalas revision (approved); keyword list and replay for 14 categories and "most often".
* In progress: Kalas mocks with the 14 categories and two new colour tokens;
* Next: owner approves the muted palette → U2 `design-spec.md`, renamed `strings.csv`, per-screen PNGs, and the final values for UX-3, UX-5 and UX-8.