docs: persona-charter + personaliseringsplan godkänd med justeringar

- Checkar in docs/31-persona-personalisering.md (nordstjärna).
- Uppdaterar docs/34-personalisering-implementation.md:
  - R7: välmående / icke-restriktiv hälsa-framing.
  - Personaliseringstexter = mallar med grundade fakta, inte fri AI-text.
  - ai_inferred-minnen: låg konfidens, användarbekräftelse, aldrig säkerhetsbeslut.
  - UPDATE_USER_MEMORY: budgettak + mock-mönster som skanning.
  - S0 får starta; S1 inväntar godkännande.
- Staging helig, prod orörd.
This commit is contained in:
Sven (AAMOS AI)
2026-08-10 02:43:13 +07:00
parent f8e00c5060
commit 16a7849e71
2 changed files with 203 additions and 20 deletions
+162
View File
@@ -0,0 +1,162 @@
# Cibello Persona & personalisering (nordstjärna)
> Detta dokument definierar **en gång** hur Cibello ska kännas personlig, så att
> alla AI-nära funktioner (sök, "vad ska vi äta", rekommendationer, proaktiva
> puffar, receptpresentation) byggs mot samma själ i stället för att uppfinnas
> per funktion. Det är en kravspec för *känslan* inte en teknisk migrering.
> Allt nedan förankras i motorer som redan finns i plattformen.
---
## 1. Nordstjärnan
Cibello är inte "ännu en receptsök". Cibello är en **Food Twin som har din rygg**:
den bär den mentala lasten kring mat åt dig, för att den faktiskt känner ditt kök,
dina smaker och ditt folk. Målet är att en vanlig, trött människa ska känna att
appen *ser* dem och gör vardagen enklare aldrig att de blir övervakade eller
bedömda.
Ledstjärna i en mening: **"Den vet var räkosten står, förstår att du tycker den
är god, och är ärlig om att den kanske minns fel."**
---
## 2. Röst & personlighet
- **Varm och mänsklig**, som någon som bor i hemmet och råkar ha koll på maten.
Erkänner suget ("jag fattar, den är ju god"), dömer aldrig.
- **Kompetent men ödmjuk**. Säker när den vet, öppen när den gissar. Skryter inte.
- **Lätt kvick** där det passar, men aldrig på användarens bekostnad och aldrig så
att skämtet skymmer nyttan.
- **Kort och konkret**. En trött människa vill ha svar, inte en essä.
- **Aldrig en robot, aldrig en tjatig coach.** Ingen pekpinne, ingen skam.
Rösten är en varumärkesegenskap den ska kunna finjusteras centralt, inte
hårdkodas per skärm.
---
## 3. Vad appen får känna till (och varifrån)
All personalisering byggs på data som redan samlas in. "Lära känna användaren" är
till stor del att *väva ihop* dessa källor inte att samla in nytt.
| Vad appen kan veta | Källa som redan finns |
| --- | --- |
| Vad du har hemma och var | `inventory_items` + `storage_locations` (+ `sublocation`) |
| Hur säker den är på att det stämmer | Trust-motorn (`trusted`/`decaying`/`stale`) |
| Vad du gillar/ogillar | `taste_signals`, betyg, laghistorik |
| Hur mycket ni brukar äta | `cooking_assumption_profiles` |
| Vilka ni är i hushållet | `household_members`, personer/portioner |
| Allergener & kostbehov | `user_health_profiles` (**alltid användarsatt**) |
| Uttalade mål & preferenser | onboarding-mål, `user_preferences` |
| Uttryckliga minnen | `memory_items` / `food_memories` ("barnen ogillar broccoli") |
| Språk | locale-preferens (×12) |
---
## 4. Grundregeln: aldrig påhittat
Detta är regeln som gör det personliga **magiskt i stället för trasigt eller
creepy**, och den är icke-förhandlingsbar:
- Appen påstår **bara** fakta som finns i verklig data. "Står i kyldörren" endast
om lager + plats säger det. Ingen påhittad hylla, ingen påhittad vara.
- Osäkerhet kommer från **trust-motorn**, aldrig från ett påklistrat skämt. En
`decaying`/`stale` vara får hedgen "…om du inte flyttat/ätit den"; en `trusted`
vara får en säker ton.
- Personalisering bygger på **observerat beteende + uttalade preferenser** aldrig
på gissningar om känsliga egenskaper.
- Detaljnivån följer datan: "i kylen" alltid, "övre hyllan till vänster" bara när
det registrerats.
Detta är samma princip som håller skanningen trovärdig, applicerad på tonen.
---
## 5. Samtycke, transparens & kontroll
"Appen känner mig" blir varmt när jag har kontroll, och kusligt när profilen är
osynlig. Därför:
- Allt appen minns ska vara **synligt och redigerbart** för användaren
(minnesskärmen). Inget hemligt profilbygge.
- Personalisering är **samtyckesgatad** och kan stängas av per kategori.
- Appen visar gärna **varför**: "jag föreslår detta för att du lagat det tre
gånger" proveniens skapar förtroende.
- Inget känsligt härleds tyst. Allergener och kostbehov **sätter användaren**.
- Radering är redan komplett (GDPR-flödet): det appen vet kan alltid tas bort.
---
## 6. Ton & välmående
En app som känner din mat måste vara snäll. Icke-förhandlingsbart:
- **Aldrig skam** för vad du äter, hur mycket, eller för svinn. Hjälp, polisa inte.
- **Ingen skadlig kaloripolisiär.** Stötta en sund relation till mat; peppa,
sänk stressen, minska svinn *varsamt* (mjölkprincips-andan riktad mot människan).
- **Säkerhet går före personlighet.** Allergenvarningar är hårda fakta, aldrig
mjukade av ton, aldrig AI-gissade.
- **Familjesäkert.** Hushåll har barn; håll språk och innehåll åldersanpassat.
---
## 7. Hur personligheten syns per funktion
Samma själ, konsekvent applicerad:
- **"Vad ska vi äta?" / rekommendationer:** tonat mot smak + vad som finns hemma +
vad som snart går ut + kostbehov. Förklarar valet kort.
- **Fritextsök (byggt):** räkost-svaret varm ton, FoodTwin-plats, trust-hedge,
aldrig tyst tomhet.
- **Proaktiva puffar (opt-in, dismissbara):** "din grädde närmar sig bäst-före
här är två recept du brukar gilla som använder den." Aldrig tjat.
- **Receptpresentation:** respektera kostbehov, flagga/dölj allergener tydligt.
- **Onboarding:** lär målen, sätt relationen hjälpsam direkt, mer personlig med
tiden.
---
## 8. Progressiv förtrogenhet
Appen ska "lära känna dig" **gradvis**: börja hjälpsam men generell, bli mer
personlig i takt med att den observerar mer och alltid förtjäna förtroendet.
Aldrig påflugen tidigt ("jag ser att du…" innan den faktiskt sett något).
---
## 9. Lokalisering av personlighet
Rösten ska **översättas, inte transkriberas** till alla 12 språk. En svensk
kvickhet motsvaras av en naturlig formulering i mål­språket, inte en ordagrann
översättning. Paritetstest gäller för alla persona-strängar precis som för övrig
i18n.
---
## 10. Cibello får ALDRIG
- hitta på fakta, platser eller varor som inte finns i datan
- gissa allergener eller kostbehov
- skämma användaren för mat, mängd eller svinn
- agera på användarens vägnar i säkerhetskritiska beslut utan bekräftelse
- exponera en hushållsmedlems privata data för en annan olämpligt
- bygga en osynlig profil användaren inte kan se, redigera eller radera
---
## 11. Koppling till befintliga motorer (så det blir ihopkoppling, inte nybygge)
| Persona-behov | Befintlig motor att väva in |
| --- | --- |
| "Vet var grejen står" | inventory + storage_locations + sublocation |
| "Ärlig om osäkerhet" | trust-motorn (states + score) |
| "Kommer ihåg mig" | memory_items / food_memories |
| "Vet vad jag gillar" | taste_signals + laghistorik |
| "Vet hur mycket vi äter" | cooking_assumption_profiles |
| "Respekterar mina behov" | user_health_profiles (användarsatt) |
| "Jag har kontroll" | user_consents + GDPR-radering (klart) |
| "Pratar mitt språk" | i18n ×12 |
Nästan varje personlig känsla har redan en motor. Uppgiften är att ge den röst.
+41 -20
View File
@@ -2,9 +2,7 @@
> Status: **plan för granskning**. Ingen funktionskod får skrivas förrän planen är godkänd.
> Omfattning: Staging endast. Prod/AAMOS förblir orörd.
> Mål: mappa persona-chartern (se `docs/31-persona-nordstjärnan.md`)* till konkreta, granskningsbara skivor som återanvänder befintliga motorer.
\* *Dokumentet `docs/31-persona-nordstjärnan.md` saknas för närvarande i repot. Planen nedan bygger på de principer och datamodeller som redan finns i Del 312, Del 29, FAS3/4-audits och minnesarkitekturen i `packages/memory-client`. Om en separat persona-charter checkas in bör den refereras explicit här innan skiva 1 påbörjas.*
> Mål: mappa persona-chartern (`docs/31-persona-personalisering.md`) till konkreta, granskningsbara skivor som återanvänder befintliga motorer.
---
@@ -13,7 +11,7 @@
| Yta | Nuvarande läge | Persona-effekt efter Spår 1 | Varför denna yta? |
| --- | --- | --- | --- |
| **A. "Vad ska vi äta?" / `GET /v1/recommendations/what-to-eat`** | ✅ Byggd. Rankar recept efter täckning, utgångsdatum, näringsfit, smak, betyg, säsong, högtid, tid, budget, variation, väder, craving. | Recept rangordnas med tydlig proveniens som inkluderar *användarens egna minnen* ("Du lagade kycklinggryta tre tisdagar i rad — här är en annan variant"), *hushållsförbrukningsmönster* och *utgångs-varor*. | Appens viktigaste surface; här märks personliga förslag mest. |
| **B. Grupperade sök-svar / recept-sök** | 🔧 Delvis byggd (`/v1/recipes/search` finns troligen; söksvar är grundade i katalogen). | Sökresultat tonas av användarens smakprofil, hushållsbegränsningar och lager. Proaktivt utesluter allergener/undvikanden. | Sök är en aktiv användarintent; personlig rangordning måste vara förklarlig. |
| **B. Grupperade sök-svar / recept-sök** | 🔧 Delvis byggd (`/v1/recipes/search` finns troligen; söksvar är grundade i katalogen). | Sökresultat tonas av användarens smakprofil, hushållsbegränsningar och lager. Proaktivt utesluter allergener/undvikanden. **Bygger PÅ befintligt grundat svar (lager + plats + trust-hedge); no-fabrication-grundningen bevaras.** | Sök är en aktiv användarintent; personlig rangordning måste vara förklarlig. |
| **C. Proaktiva puffar** | 🔧 `SEND_EXPIRY_NOTIFICATION` körs dagligen kl 07. Matlådepåminnelser finns. | Nya puffar: "Gurkan börjar se trött ut — tre recept du brukar gilla med gurka", "Ni har ätit risotto ofta på söndagar; vill du planera en?" | Hög användarnytta, låg frekvens, kräver explicit opt-in. |
| **D. Receptrangordning efter smak/hälsa/lager** | ✅ Motor finns (`packages/recommendation-engine/src/scoring.ts`). | Skapa tre fördefinierade vyer: **Smak** (favoritkök + taste_signals), **Hälsa** (näring mot dagsmål + health_profile), **Lager** (täckning + utgår-snart). Användaren växlar; ingen hemlig viktning. | Ger användaren kontroll och transparens. |
| **E. Onboarding-relationen** | ✅ Onboarding med mål, allergier, favoritkök. | Onboarding-klassifikationer skrivs som `user_stated`-minnen och `taste_signals`; de synkroniseras tillbaka till "Vad plattformen vet om mig". | Tidigt förtroende: användaren ser att svaren används. |
@@ -64,11 +62,15 @@ Persona-chartern översätts till följande tekniska regler. Varje regel ska gå
### R1. Grundat, aldrig påhittat
- Alla personliga påståenden måste ha ett spårbart ursprung i `memory_items.origin` (`user_stated`, `observed`, `ai_inferred`).
- `ai_inferred`-poster visas aldrig utan att användaren kan se att det är ett "mönster vi har observerat" och kan pausa/radera.
- `ai_inferred`-poster:
- Har **låg startkonfidens** (t.ex. 0.5).
- Formuleras som "ett mönster vi sett", aldrig "du gillar".
- Kräver **användarbekräftelse eller avfärdande** innan de påverkar rekommendationer som säkerhetsbeslut.
- Driver **aldrig** säkerhetsbeslut (allergen/diet/exkludering).
- Ingen AI får fabricera recept, ingredienser eller påståenden om användaren.
### R2. Samtycke + synligt/redigerbart minne
- `personalization`-samtycke krävs för alla personliga ytor (redan i `userConsents`).
- `personalization`-samtycke krävs för alla personliga ytor (redan i `userConsents`). **Enkeltflaggat samtycke är OK för Spår 1**; granulär uppdelning skjuts till senare spår om behov uppstår.
- "Vad plattformen vet om mig" (`GET /v1/me/memory`) visar alla minnen, inklusive ursprung och konfidens.
- Användaren kan rätta (`PATCH /v1/me/memory/:id`), pausa (`POST /v1/me/memory/pause-all`) och radera (`DELETE /v1/me/memory/:id` samt `DELETE /v1/me/memory`).
- Användarkorrigering ändrar `origin` till `user_stated` och `confidence` till `1`.
@@ -91,13 +93,23 @@ Persona-chartern översätts till följande tekniska regler. Varje regel ska gå
### R6. Proveniens
- Varje personaliserat förslag ska kunna förklara *varför* det valdes.
- Exempel på provenienssträngar:
- "För att du har berättat att du gillar italienskt kök."
- "För att ni har tre ägg som bör användas inom två dagar."
- "För att du lagat kycklinggryta tre gånger den senaste månaden."
- "För att det passar ditt återstående proteinbehov i dag."
- **Personaliseringstexter (proveniens, why, puffar) genereras från mallar med grundade fakta**, inte fri AI-text. Mallarna är översatta, skam- och fabriceringsfria per konstruktion.
- Exempel på mallar (svenska):
- `"För att du har berättat att du gillar {{cuisine}}."`
- `"För att ni har {{count}} {{ingredient}} som bör användas inom {{days}} dagar."`
- `"För att du lagat {{recipe}} {{count}} gånger den senaste månaden."`
- `"För att det passar ditt återstående proteinbehov i dag."`
- Förbudslistan (R3) behålls som skyddsnät för mall-renderade strängar.
- **Fri AI-text får endast användas för `ai_inferred`-minnesförslag** (events-only + Zod + användarbekräftelse).
- Proveniens lagras/transporteras i `ScoredRecommendation.parts` + en ny valfri `provenance` array.
### R7. Välmående — icke-restriktiv hälsa-framing
- Hälso-vyn och all näringsmåls-framing ska vara **stödjande och icke-restriktiv**.
- Tillåten copy: `"Passar ditt proteinmål"`, `"Bidrar till dina grönsaker i dag"`.
- **Förbjuden copy:** `"Du har överskridit ditt kalorimål"`, `"Bara X kcal kvar"`, `"Begränsa dig"`, `"Undvik …"` eller annan negativ/restriktiv framing.
- Näringsmål visas endast för användare som själva har satt dem i `userHealthProfiles`/`userPreferences`.
- Copy-granskning + eval-fall ska täcka välmående-framing.
---
## 4. SKIVINDELNING — små reviewbara skivor med testplan
@@ -106,14 +118,16 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
### Skiva S0 — förberedelse (inga användarfunktioner)
**Innehåll:**
- Checka in `docs/31-persona-nordstjärnan.md` om den finns separat; annars lyft in charter-reglerna ovan i Del 34.
- Säkerställ att `userConsents` för `personalization` läses korrekt överallt.
- Checka in `docs/31-persona-nordstjärnan.md` och förankra R1R7 explicit mot varje avsnitt i chartern.
- Säkerställ att `userConsents` för `personalization` läses korrekt överallt. **Enkeltflaggat `personalization`-samtycke är OK för Spår 1** (ingen granulär uppdelning av personalisering ännu).
- Uppdatera `packages/recommendation-engine/src/types.ts` med `provenance` och `memorySignalIds``ScoredRecommendation`.
- Skriv test-fixtur för `taste_signals`, `memory_items`, `cooking_assumption_profiles`.
- Sätt upp budgettak + mock-testmönster för `UPDATE_USER_MEMORY` (samma mönster som skanning: `GEMINI_DAILY_BUDGET_USD`, `MockAamosClient`, hermetiska tester).
**Testplan:**
- Typecheck och enhetstester gröna.
- Fixturen kan skapa en användare med samtycken, minnen, smaksignaler och matlagningshistorik.
- `UPDATE_USER_MEMORY`-anrop kan mockas och kostnadsräknas utan att träffa AAMOS.
**Estimat:** 1 dag.
@@ -168,6 +182,8 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
- Koppla minnen till reella ytor: t.ex. "Du gillar italienskt kök" → visar vilka recept som påverkas.
- Lägg till `GET /v1/me/memory/impact` som returnerar vilka rekommendationer som påverkas av ett specifikt minne (utan att exponera andras data).
- Förbättra `UPDATE_USER_MEMORY`-jobbet:
- Använd samma budgettak + kostnadsräkning som skanning (`packages/ai-contracts/src/gemini.ts`, `GEMINI_DAILY_BUDGET_USD`).
- Hermetiska tester med `MockAamosClient` (inga API-nycklar i tester, inga subagents).
- Be AAMOS om nya minnesförslag med explicit prompt som förbjuder påhitt.
- Validera output mot Zod-kontraktet.
- Avvisa förslag som saknar stöd i events.
@@ -257,13 +273,17 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
## Godkännande-checklista för planen
- [ ] Persona-charter (`docs/31-persona-nordstjärnan.md`) checkas in eller refereras korrekt.
- [ ] Yt-inventeringen täcker alla AI-nära ytor som ska personaliseras i Spår 1.
- [ ] Motor-mappningen anger befintliga motorer/data för varje yta; inga parallella motorer.
- [ ] Charter-reglerna (R1R6) är tydliga och testbara.
- [ ] Skivindelningen är tillräckligt liten; varje skiva har testplan.
- [ ] Risker och testmetoder accepteras.
- [ ] Ingen kod skrivs förrän denna plan är godkänd.
- [x] Persona-charter (`docs/31-persona-personalisering.md`) checkas in och förankras.
- [x] Yt-inventeringen täcker alla AI-nära ytor som ska personaliseras i Spår 1.
- [x] Motor-mappningen anger befintliga motorer/data för varje yta; inga parallella motorer.
- [x] Charter-reglerna (R1R7) är tydliga och testbara.
- [x] Personaliseringstexter = mallar med grundade fakta, inte fri AI-text.
- [x] `ai_inferred`-minnen: låg konfidens, användarbekräftelse, driver inte säkerhetsbeslut.
- [x] `UPDATE_USER_MEMORY`: budgettak + mock-mönster som skanning.
- [x] Skivindelningen är tillräckligt liten; varje skiva har testplan.
- [x] Risker och testmetoder accepteras.
- [x] Ingen kod skrivs förrän denna plan är godkänd.
- [x] S0 får starta; S1 påbörjas efter godkännande.
---
@@ -272,3 +292,4 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
| Datum | Revision | Författare |
| --- | --- | --- |
| 2026-08-10 | Initial plan för granskning | Sven |
| 2026-08-10 | Godkänd med justeringar: R7 välmående, mall-baserade texter, ai_inferred-konfidens, UPDATE_USER_MEMORY-budget, docs/31 incheckad | Sven / Johan |