ci: trigga på master + formatfix inför Gitea Actions
CI / Typecheck, test & build (push) Failing after 2s
CI / Typecheck, test & build (push) Failing after 2s
This commit is contained in:
@@ -8,15 +8,16 @@
|
||||
|
||||
## 1. YT-INVENTERING — vilka AI-nära ytor ska personaliseras
|
||||
|
||||
| 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. **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. |
|
||||
| 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. **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. |
|
||||
|
||||
**Out of scope för Spår 1 (sparas till senare spår):**
|
||||
|
||||
- Generering av helt nya recept utifrån minne.
|
||||
- Community/creator-personalisering.
|
||||
- Extern hälsointegration (HealthKit/Health Connect).
|
||||
@@ -29,13 +30,13 @@
|
||||
|
||||
För varje yta anger tabellen **vilken befintlig data/motor** som är primär källa. Ingen ny AI-motor ska byggas för Spår 1; personalisering = att låta befintliga motorer läsa mer kontext.
|
||||
|
||||
| Yta | Primär befintlig data/motor | Ny data vi läser in (ingen ny motor) | Vad vi INTE bygger |
|
||||
| --- | --- | --- | --- |
|
||||
| A. Vad ska vi äta? | `recommendation-engine` (`scoreCandidate`/`rankAll`) | `memory_items` (smak/faktum/mönster), `taste_signals` (axelriktning), `cooking_assumption_profiles` (förbrukningsmönster), `recipe_cooks` (senast lagat), `recipe_ratings` (egna betyg). | Ingen ny rankningsmotor. |
|
||||
| B. Sök-svar | Recept-katalog + `recipe-engine` (säkerhet/täckning) | Samma som A plus `userPreferences` (favoriteCuisines, avoidIngredientIds, spiceLevelMax). | Ingen separat sök-AI. |
|
||||
| C. Proaktiva puffar | `inventory-engine/forecast.ts`, `reconciliation.ts`, `worker`-schemaläggare | `memory_items.recipe_memory`, `recipe_cooks`, `taste_signals`, `userConsents` (opt-in). | Ingen ny notismotor. |
|
||||
| D. Smak/Hälsa/Lager-vyer | `recommendation-engine` + `nutrition-engine` | `userPreferences`, `userHealthProfiles`, dagens `meals`, lager. | Ingen ny vy-motor; bara fördefinierade vikter. |
|
||||
| E. Onboarding | Onboarding-flödet i `apps/mobile` | Skriver till `memory_items` + `taste_signals` via befintliga API-routes. | Ingen ny onboarding-backend. |
|
||||
| Yta | Primär befintlig data/motor | Ny data vi läser in (ingen ny motor) | Vad vi INTE bygger |
|
||||
| ------------------------ | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
||||
| A. Vad ska vi äta? | `recommendation-engine` (`scoreCandidate`/`rankAll`) | `memory_items` (smak/faktum/mönster), `taste_signals` (axelriktning), `cooking_assumption_profiles` (förbrukningsmönster), `recipe_cooks` (senast lagat), `recipe_ratings` (egna betyg). | Ingen ny rankningsmotor. |
|
||||
| B. Sök-svar | Recept-katalog + `recipe-engine` (säkerhet/täckning) | Samma som A plus `userPreferences` (favoriteCuisines, avoidIngredientIds, spiceLevelMax). | Ingen separat sök-AI. |
|
||||
| C. Proaktiva puffar | `inventory-engine/forecast.ts`, `reconciliation.ts`, `worker`-schemaläggare | `memory_items.recipe_memory`, `recipe_cooks`, `taste_signals`, `userConsents` (opt-in). | Ingen ny notismotor. |
|
||||
| D. Smak/Hälsa/Lager-vyer | `recommendation-engine` + `nutrition-engine` | `userPreferences`, `userHealthProfiles`, dagens `meals`, lager. | Ingen ny vy-motor; bara fördefinierade vikter. |
|
||||
| E. Onboarding | Onboarding-flödet i `apps/mobile` | Skriver till `memory_items` + `taste_signals` via befintliga API-routes. | Ingen ny onboarding-backend. |
|
||||
|
||||
**Centrala datatabeller som används av flera ytor:**
|
||||
|
||||
@@ -61,6 +62,7 @@ För varje yta anger tabellen **vilken befintlig data/motor** som är primär k
|
||||
Persona-chartern översätts till följande tekniska regler. Varje regel ska gå att granska i kod och test.
|
||||
|
||||
### 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:
|
||||
- Har **låg startkonfidens** (t.ex. 0.5).
|
||||
@@ -70,29 +72,34 @@ Persona-chartern översätts till följande tekniska regler. Varje regel ska gå
|
||||
- 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`). **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`.
|
||||
|
||||
### R3. Ingen skam-ton
|
||||
|
||||
- Förklaringar (`whySv`) får aldrig innehålla skam, moralisering eller värdeomdömen om matvanor.
|
||||
- Exempel på förbjuden copy: "Du borde äta mindre kött", "Din kost är obalanserad".
|
||||
- Tillåten copy: "Denna rätt ger 35 g protein, vilket matchar ditt mål", "Du har lagat risotto ofta på söndagar — här är en variation".
|
||||
- Enhetstester ska validera copy mot en förbudslista.
|
||||
|
||||
### R4. Allergener/hälsa användarsatt
|
||||
|
||||
- Allergener kommer från `userPreferences.allergens` + hushållsaggregering (strängaste gäller), aldrig från AI.
|
||||
- Hälsodata (`userHealthProfiles`) är frivillig och användarsatt; appen visar icke-medicinsk disclaimer.
|
||||
- Recept-allergener fortsätter att härledas deterministiskt från `canonical_ingredients.allergens` (se Del 33 / allergen-invariant-testet).
|
||||
|
||||
### R5. i18n × 12
|
||||
|
||||
- Alla nya användarvisningstexter ska gå via `localeContext` och `memory-client/renderMemorySummary`.
|
||||
- Proveniessatser genereras med språkspecifika mallar (sv/en/es/it/de/fr/da/nb/fi/nl/pl/pt).
|
||||
- Förklaringar (`whySv`) ska ha motsvarande `whyEn`, `whyEs`, … eller genereras dynamiskt från mallar.
|
||||
|
||||
### R6. Proveniens
|
||||
- Varje personaliserat förslag ska kunna förklara *varför* det valdes.
|
||||
|
||||
- Varje personaliserat förslag ska kunna förklara _varför_ det valdes.
|
||||
- **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}}."`
|
||||
@@ -104,6 +111,7 @@ Persona-chartern översätts till följande tekniska regler. Varje regel ska gå
|
||||
- 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.
|
||||
@@ -117,7 +125,9 @@ Persona-chartern översätts till följande tekniska regler. Varje regel ska gå
|
||||
Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva levererar: kod + enhetstester + integrationstest mot staging-DB + dokumentationsuppdatering.
|
||||
|
||||
### Skiva S0 — förberedelse (inga användarfunktioner)
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- Checka in `docs/31-persona-nordstjärnan.md` och förankra R1–R7 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` på `ScoredRecommendation`.
|
||||
@@ -125,6 +135,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- 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.
|
||||
@@ -134,7 +145,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
---
|
||||
|
||||
### Skiva S1 — "Vad ska vi äta?" tonad mot lager + utgår-snart + smak + proveniens
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- Utöka `recommendation-engine/src/scoring.ts` med tre nya delpoäng som läser befintliga tabeller:
|
||||
- `memoryFit`: positiv boost om recept matchar `memory_items` (t.ex. favoritkök, gillade rätter).
|
||||
- `tasteFit`: boost/penalty från `taste_signals` per axel.
|
||||
@@ -145,6 +158,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- Hård krav: `personalization`-samtycke måste vara `granted`; annars används nuvarande beteende.
|
||||
|
||||
**Testplan:**
|
||||
|
||||
- Enhetstest: en kandidat med `taste_signals` (positiv/negativ) får rätt `tasteFit`.
|
||||
- Enhetstest: `memoryFit` boostas av `verifiedByUser`-minne mer än `ai_inferred`.
|
||||
- Enhetstest: `cookingAssumptionFit` boostar recept som använder ingredienser med hög `averageEatenPortions`.
|
||||
@@ -156,7 +170,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
---
|
||||
|
||||
### Skiva S2 — Proaktiva puffar (opt-in)
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- Ny jobbtyp `SEND_PERSONALIZED_NUDGE` i worker (BullMQ-schemaläggare, t.ex. kl 11:00 på helger och kl 16:00 på vardagar).
|
||||
- Logik:
|
||||
1. Hämta hushåll med `personalization`-samtycke.
|
||||
@@ -167,6 +183,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- Proveniens: "Gurkan håller på att bli slapp — här är ett recept du brukar gilla."
|
||||
|
||||
**Testplan:**
|
||||
|
||||
- Enhetstest: puff genereras endast om det finns utgående vara + matchande recept + samtycke.
|
||||
- Enhetstest: max 1 puff per hushåll per dag.
|
||||
- Integrationstest: jobbet kör mot staging-DB och skapar rätt notis.
|
||||
@@ -177,7 +194,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
---
|
||||
|
||||
### Skiva S3 — Minnes-ytan + personliga grundade svar
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- Förbättra `GET /v1/me/memory` så minnen visas med tydligare ursprung och användbara kategorier.
|
||||
- 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).
|
||||
@@ -189,6 +208,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- Avvisa förslag som saknar stöd i events.
|
||||
|
||||
**Testplan:**
|
||||
|
||||
- Enhetstest: `buildMemoryOverview` grupperar rätt och visar pausade poster.
|
||||
- Integrationstest: `PATCH /v1/me/memory/:id` ändrar `origin` till `user_stated`.
|
||||
- Mock-test: `UPDATE_USER_MEMORY` avvisar fabricerat minne (t.ex. påhittad favoriträtt).
|
||||
@@ -199,7 +219,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
---
|
||||
|
||||
### Skiva S4 — Smak / Hälsa / Lager-vyer i "Vad ska vi äta?"
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- Lägg till query-param `view=default|taste|health|pantry` på `GET /v1/recommendations/what-to-eat`.
|
||||
- Varje vy använder samma `rankAll` men med fördefinierade `ScoringWeights`:
|
||||
- **Taste**: högre `taste`, `craving`, `memoryFit`, `rating`; lägre `nutritionFit`.
|
||||
@@ -208,6 +230,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- Spara vikterna i `packages/recommendation-engine/src/types.ts` som konstanter.
|
||||
|
||||
**Testplan:**
|
||||
|
||||
- Enhetstest: samma kandidater ger olika ordning beroende på vy.
|
||||
- Integrationstest: API accepterar `view`-parametern och returnerar skilda topplistor.
|
||||
- Regressionstest: `default` är oförändrad gentemot idag.
|
||||
@@ -217,7 +240,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
---
|
||||
|
||||
### Skiva S5 — Onboarding → minne + smaksignaler
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- När användaren slutför onboarding skrivs mål, allergier, favoritkök, undvikanden och spice max till:
|
||||
- `userPreferences` (redan idag).
|
||||
- `memory_items` som `user_stated`-poster.
|
||||
@@ -225,6 +250,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- Visa i onboarding: "Detta sparas i "Vad plattformen vet om mig" och du kan ändra det när som helst."
|
||||
|
||||
**Testplan:**
|
||||
|
||||
- Integrationstest: efter onboarding finns motsvarande `memory_items` och `taste_signals`.
|
||||
- Enhetstest: onboarding-favoritkök skapar rätt `taste_signals`-poster.
|
||||
|
||||
@@ -233,7 +259,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
---
|
||||
|
||||
### Skiva S6 — i18n, proveniens och eval-pipeline
|
||||
|
||||
**Innehåll:**
|
||||
|
||||
- Säkerställ att alla nya provenienssträngar finns på 12 språk.
|
||||
- Uppdatera `memory-client/renderMemorySummary` med nya value-former.
|
||||
- Lägg till AI-eval-fall i `ai_eval_cases` för:
|
||||
@@ -243,6 +271,7 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
- Kör evals mot AAMOS i staging.
|
||||
|
||||
**Testplan:**
|
||||
|
||||
- Evals körbara via adminpanel eller worker-jobb.
|
||||
- Manuell granskning av 50 genererade `whySv` per språk.
|
||||
|
||||
@@ -256,18 +285,18 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
|
||||
## 5. RISKER + hur varje charter-regel testas
|
||||
|
||||
| Risk | Mitigering | Test/verifiering |
|
||||
| --- | --- | --- |
|
||||
| Risk | Mitigering | Test/verifiering |
|
||||
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **AI fabricerar minnen eller påhittar användarpreferenser** | `UPDATE_USER_MEMORY` tar bara events som input; output valideras mot Zod; `ai_inferred`-poster visas med tydlig etikett; användaren kan radera/pausa. | Mock-test där AAMOS föreslår ett minne som inte stöds av events → avvisas. Invariant: alla `memory_items` måste ha `origin` satt. |
|
||||
| **Personliga data läcker till andra hushållsmedlemmar** | `userHealthProfiles`, `memory_items`, `taste_signals` är användarsatta; hushållsaggregering är begränsad till allergener/undvikanden/spice max. | Integrationstest: medlem A kan inte läsa medlem B:s `memory_items` eller hälsoprofil. |
|
||||
| **Skam-ton eller värderande copy** | Förbudslista + språkgranskning i `explain.ts` och nudge-generering. | Enhetstest som skannar 100+ genererade förklaringar mot förbudslista; eval-korpus med skam-exempel. |
|
||||
| **Användaren tappar kontroll över minnet** | Full CRUD + paus + radera allt; alla nya minnen kommer från användaren eller observerade events. | Manuell test av "Vad plattformen vet om mig"-flödet; GDPR-raderingstest. |
|
||||
| **Personalisering körs utan samtycke** | Hård check på `userConsents.kind='personalization' AND status='granted'` i API och worker. | Integrationstest: utan samtycke fallback till opersonligt beteende; inga `memory_items` skrivs. |
|
||||
| **Allergener eller hälsa härleds felaktigt av AI** | Allergener kommer från användarpreferenser + canonical-ingredienser; hälsa är användarsatt. AI används aldrig för säkerhetsfiltrering. | Återanvänd befintliga säkerhetstester (`recipe-engine/test/safety.test.ts`) och allergen-invariant-testet. |
|
||||
| **i18n-försämring / fel språk i proveniens** | Alla nya texter via `localeContext` och språkspecifika mallar; eval per språk. | Manuell granskning per språk; automatisk check att `whySv` inte blandas med `whyEn`. |
|
||||
| **Prestandaförsämring i "Vad ska vi äta?"** | Läsning av `memory_items` och `taste_signals` är indexerad; begränsa till aktuell användare/hushåll; cache lämpliga aggregeringar. | Lasttest: 200 anrop/minut under 5 minuter; jämför svarstid före/efter. |
|
||||
| **Cirkulära beroenden** | Alla ändringar i `recommendation-engine` får inte bero på `apps/api`; `memory-client` får inte bero på `recommendation-engine`. | `pnpm typecheck` och dependency-graf (turbo) grön. |
|
||||
| **Seed/reseed bryter personliga data** | Inga personliga data i seed; seed skrivs aldrig över användardata. | Seed-test: efter `db:test-setup` finns inga `memory_items` eller `taste_signals` för testanvändare. |
|
||||
| **Personliga data läcker till andra hushållsmedlemmar** | `userHealthProfiles`, `memory_items`, `taste_signals` är användarsatta; hushållsaggregering är begränsad till allergener/undvikanden/spice max. | Integrationstest: medlem A kan inte läsa medlem B:s `memory_items` eller hälsoprofil. |
|
||||
| **Skam-ton eller värderande copy** | Förbudslista + språkgranskning i `explain.ts` och nudge-generering. | Enhetstest som skannar 100+ genererade förklaringar mot förbudslista; eval-korpus med skam-exempel. |
|
||||
| **Användaren tappar kontroll över minnet** | Full CRUD + paus + radera allt; alla nya minnen kommer från användaren eller observerade events. | Manuell test av "Vad plattformen vet om mig"-flödet; GDPR-raderingstest. |
|
||||
| **Personalisering körs utan samtycke** | Hård check på `userConsents.kind='personalization' AND status='granted'` i API och worker. | Integrationstest: utan samtycke fallback till opersonligt beteende; inga `memory_items` skrivs. |
|
||||
| **Allergener eller hälsa härleds felaktigt av AI** | Allergener kommer från användarpreferenser + canonical-ingredienser; hälsa är användarsatt. AI används aldrig för säkerhetsfiltrering. | Återanvänd befintliga säkerhetstester (`recipe-engine/test/safety.test.ts`) och allergen-invariant-testet. |
|
||||
| **i18n-försämring / fel språk i proveniens** | Alla nya texter via `localeContext` och språkspecifika mallar; eval per språk. | Manuell granskning per språk; automatisk check att `whySv` inte blandas med `whyEn`. |
|
||||
| **Prestandaförsämring i "Vad ska vi äta?"** | Läsning av `memory_items` och `taste_signals` är indexerad; begränsa till aktuell användare/hushåll; cache lämpliga aggregeringar. | Lasttest: 200 anrop/minut under 5 minuter; jämför svarstid före/efter. |
|
||||
| **Cirkulära beroenden** | Alla ändringar i `recommendation-engine` får inte bero på `apps/api`; `memory-client` får inte bero på `recommendation-engine`. | `pnpm typecheck` och dependency-graf (turbo) grön. |
|
||||
| **Seed/reseed bryter personliga data** | Inga personliga data i seed; seed skrivs aldrig över användardata. | Seed-test: efter `db:test-setup` finns inga `memory_items` eller `taste_signals` för testanvändare. |
|
||||
|
||||
---
|
||||
|
||||
@@ -289,9 +318,9 @@ Ingen skiva får påbörjas förrän föregående är godkänd. Varje skiva leve
|
||||
|
||||
## Revisionslogg
|
||||
|
||||
| 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 |
|
||||
| 2026-08-10 | S1 implementerat: "Vad ska vi äta?" med provenansmallar, samtyckesgrind, personliga delpoäng, integrationstester; commit `0885f5b` | Sven / Johan |
|
||||
| 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 |
|
||||
| 2026-08-10 | S1 implementerat: "Vad ska vi äta?" med provenansmallar, samtyckesgrind, personliga delpoäng, integrationstester; commit `0885f5b` | Sven / Johan |
|
||||
| 2026-08-10 | S2 implementerat: proaktiva puffar (expiring-ingredient) med dubbelgrind, 12-språksmallar, frekvens-/duplicate-gate, UTC-matte, integrationstester; commit `f494b18` | Sven / Johan |
|
||||
|
||||
Reference in New Issue
Block a user