Receptnamnet ska beskriva rätten, inte förvaringen. Skolstart-/matlåde-
kopplingen ligger kvar i taggar (skolstart, meal_prep) och beskrivningen.
Slug oförändrad så omseedning uppdaterar receptet på plats.
Buggen: när användaren uttryckligen valde en högtid (t.ex. Kräftskiva), en
tagg (Baka) eller sökte, hårdfiltrerade scoreCandidate bort alla recept vars
totalTimeMinutes översteg hushållets maxCookingMinutesWeekday (parts.time=-1,
rankAll släpper <0). De smala högtidspoolerna kollapsade då till 0-1 recept
trots att flera fanns korrekt taggade.
Reproducerat mot riktig seedad databas: med en 20-min vardagsgräns gav
kräftskiva 2, grillsäsong 2, skolstart 0, bak nästan tomt. Med fixen ger de
4, 5, 3 respektive 18 – medan standardvyn "Rekommenderat" fortfarande
respekterar tidsgränsen (3 snabba middagar).
Fix: uttrycklig avsikt (holiday/tag/search) förbigår vardagens tidsgräns –
tiden blir mjuk rankning i stället för hårt filter. En uttrycklig q.maxMinutes
i förfrågan respekteras fortfarande. Regressionstest låser mekanismen.
Ratta slug-bugg: recept-taggen "grillsäsong" matchade aldrig event-sluggen
"grillsasong" (ASCII) sa grillsäsong-knappen visade inget. Nu ratt.
15 nya hogtidsrecept taggade med exakt SE-event-slug: rodbetssallad, rodkal,
senapssill, stekt prinskorv, kokta kraftor med krondill, aioli, ostbricka,
farskpotatis med dill, agghalvor med rakror, rakcocktail, grillspett med
halloumi, grillad kycklingfile, pastasallad i matladan, tillbehor till
surstromming, kryddig kyckling med ris.
Omtaggar befintliga recept till ratt hogtid: vasterbottensostpaj +kraftskiva,
grekisk-sallad +grillsasong, chili/spaghetti +skolstart, chokladtarta
+alla-hjartans-dag, tomatsoppa +halloween, korvgratang +oktoberfest,
halloumiburgare +valborg.
Alla 14 SE-hogtider har nu minst ett korrekt taggat recept. Naring och
enheter ar berakningsbara for alla 74 extrarecept (invarianttest gront,
repo-typecheck gront).
Kvitto-skanning (rapporterad krasch 'svar matchar inte schema … invalid value'):
- AI-skan-enheter (kvitto/kyl/maltid) normaliseras nu fore validering:
'st'->COUNT, 'kg'->KILOGRAM, 'forp'/'pase'->PACKAGE osv. Okand enhet -> null
i stallet for att falla hela svaret. Skarpt kvitto-prompt med exakt enhetslista.
17 nya tester bevisar normaliseringen.
Sok pa 'Vad ska vi ata':
- Endast TITELN (inte beskrivningen) -> 'pannkaka' ger inte langre appelkompott
(som bara namnde pannkakor i beskrivningen).
- Stavningstolerant via trigram-similarity: 'pankakor' hittar pannkakor.
Hogtidsknapparna (kraftskiva/grill/jul ...):
- Filtrerar nu pa recept-holidayTag (slug) i stallet for en titelsok som gav
tomt. Har event inga recept an visas ett arligt tomt-lage.
Full typecheck gron, ai-contracts 24 tester grona.
- Sok fungerar nu: what-to-eat tar ?search= och filtrerar recept pa titel/
beskrivning BLAND ALLA recept (t.ex. 'pannkaka' hittar pannkakor), oavsett
vald flik. Sokrutan skickar nu search i stallet for craving.
- Hogtids-/sasongsknapparna (kraftskiva, grill, skolstart) ligger nu direkt
UNDER sokrutan, inte nere bland recept-forslagen.
- Saffransbullar + lussekatter ur 'Frukost' (mealTypes dessert+breakfast ->
dessert). Bakverk hor inte till frukost i Sverige.
- Bort med 'Alla recept & sok'-lanken pa forstasidan och 'Bladdra bland recept'
pa Hemma - allt nas nu via flikarna/soket pa 'Vad ska vi ata'.
Full typecheck gron.
Alla kategori-flikar anvander nu SAMMA rekommendations-motor (what-to-eat)
som 'Rekommenderat', sa vyn blir identisk overallt:
- sok fungerar i alla flikar, %-hemma och stjarnor visas, samma kort-layout,
och samma paginering med 'Visa fler' (5 at gangen).
- Backend: what-to-eat tar nu valfri ?tag= (Baka-fliken filtrerar pa 'baking'
i stallet for maltidstyp; mealType styr bara poangsattningen).
- Enhetliga chip-rutor: Button far en style-prop, flikarna ligger i 2 kolumner
med lika bred ruta (48%), centrerad text som krymper vid behov.
- 'Toppval' visas bara pa forsta sidan. 'Alla recept & sok' kvar som lank.
Full typecheck 20/20.
Kategorisering (din notis - bakverk hor till Baka, inte mellanmal):
- Sub-typer bread/bun/pie/cake/cookie i RECIPE_TAGS.
- Bullar/kakor/pajer/chokladbollar -> dessert (inte snack) + sub-tagg; brod
-> breakfast. Befintliga lussekatter/saffransbullar taggas 'bun'.
- Browse: sub-chips under Baka (Brod/Bullar/Paj/Tartor & kakor/Smakakor).
Bladdra pa forstasidan (din onskan):
- Kategori-genvagar pa 'Vad ska vi ata' -> oppnar bladdraren forvald
(/recipes?cat=). recipes.tsx laser ?cat=.
Relevantare 'Vad ska vi ata' (snurrar samma triviala):
- view=pantry -> view=default (tackning vager tungt men inte allenaradande,
ger variation), limit 15 -> 30 (storre pool sa 'Visa fler' upprepar senare).
Felsokning inkopslista:
- Tydligare felmeddelande (HTTP-status vs natverksfel) sa root cause syns.
Full typecheck 20/20, invariant-test gront.
- Ny 'baking'-tagg (RECIPE_TAGS, text[] - ingen migration). Browse-vyn far
en 'Baka'-chip som filtrerar pa taggen; befintliga lussekatter +
saffransbullar taggas ocksa.
- extra-recipes.ts: 16 nya recept som fyller de glesa kategorierna -
4 bak (kanelbullar, kardemummabullar, appelsmulpaj, frukostfrallor),
3 frukost, 3 mellanmal (tomma kategorin -> fylld), 3 efterratt, 3 lunch.
- Endast verifierade canonical-ingredienser + berakningsbara enheter, sa
seed harleder narings-/allergendata utan att krascha (run.ts 675/691).
- Nytt rent invariant-test (ingen DB) kor riktiga computeRecipeNutrition pa
alla 16: id:n finns, naring berakningsbar, inga slug-krockar. 5 tester grona.
- Seed ar additiv (onConflictDoUpdate) - 'pnpm db:seed' lagger till + taggar
om utan dataforlust. Full typecheck 20/20.
- DIET_PATTERNS: +nordic, +carnivore, +paleo (migration 0029). Ingen separat
"lchf" - LCHF tacks av befintliga "low_carb" for att undvika dubblett med
keto/low_carb. UI visar low_carb med etiketten "LCHF".
- Mobil onboarding + profil: 9 rena val (allatare..carnivore), 12 sprak.
- recommendation-engine: ny mjuk dietAffinity-poangterm (0-1, neutral 0.5).
Rankar recept mot matvanan - ALDRIG hart filter (uteslutande matvanor,
religion, allergener hanteras redan deterministiskt i sakerhetsfiltret).
low_carb/keto: lag kolhydrat. carnivore: hog protein + lag kolhydrat.
paleo: glutenfri/laktosfri-proxyer. nordic: svenskt/nordiskt kok + sasong.
- 6 nya tester (35 grona). Full typecheck 20/20 + mobil gron.
Koden/docs pastod overallt gemini-3.5-flash-lite fast .env kor 3.1. Nu enhetligt
3.1 i .env.example, config.ts-default, gemini.ts-default, tester, eval och docs
(09 + 10). Dessutom en RIKTIG bugg: estimateCostUsd rakna pa 3.5-priser
($0,30/$2,50) medan vi kor 3.1 -> overskattade spend och troffade budgetlarmet
for tidigt. Nu 3.1-priser ($0,25/$1,50). docs/10 helt omraknad pa 3.1 (per
uppgift, per anvandare, skala, 100k-trial-scenariot). Referenslinje kvar som
visar 3.5-priset for att motivera valet.
Prompten bad modellen uppskatta *andel av en forpackning* (0.0-1.0), vilket gav
nonsens som "keso 0,8 paket", "smetana 0,6 paket", "matrester 0,5 paket". Ny
ordning enligt Johans onskan: 1) las vikt/volym om den syns (500 g, 4 dl) 2)
annars rakna hela forpackningar som heltal + "st" 3) oppnad vara: uppskatta
kvarvarande i dl/g 4) vet ej -> 1 st. Aldrig decimaler av paket. La ocksa till
regel: samma vara i flera foton listas EN gang. promptVersion -> gemini-fridge-v4.
- BUGG: kitchen hamtade ?limit=500 men schemat tillat max 200 -> 400-fel nar man
gick in i matlager / tryckte "+N till". Hojer inventoryQuerySchema.limit till 500.
- Hem: tar bort den roriga inline-listan (matlager lag kvar under Hemma). Ersatts
med ett "Matlager"-kort med genvagsknappar per plats (Kyl/Frys/Skafferi) + "Allt".
- Matlager-skarmen: grupperad per plats med rubrik + antal, sorterad pa namn,
plats-filter via chips ELLER djuplank (?loc=), sok, markera flera, massradering.
- Byter skarmtitel "Ditt kok" -> "Matlager".
- Fixar aven en latent hooks-ordningsbugg i home (useFocusEffect efter early return).
Dedup vid /v1/scans/:id/confirm matchade bara pa exakt (skiftlageskansligt)
namn eller identiskt katalog-id, sa omfotografering av samma hylla skapade
dubbletter. Ny normalizeItemName (gemener, accenter, storlek bort; behaller
fetthalt-siffror) + matchning pa katalog-id ELLER normaliserat namn mot
aktivt hushallslager.
Mobil: 'Ta bort' fanns bara i Ditt kok. Lade borttag pa startsidans
lager-rader (befintlig DELETE /v1/inventory/items/:id).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZdew6cWn1MeHqoYWFfxzo
Forra andringen blev for strikt: modellen nollade ALLA datum eftersom svenska
stamplar (DDMMYY/YYMMDD) alltid ar "tvetydiga". Nu far modellen dagens datum
och tolkar 2-siffriga artal som narmaste rimliga ar runt idag (04-09-26 ->
2026-09-04, inte 2024). Kod-sparren isPlausibleFoodDate star kvar som skydd mot
grova fel. promptVersion -> gemini-fridge-v3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZdew6cWn1MeHqoYWFfxzo
Gemini gissade fel artal pa kryptiska tryckstamplar (t.ex. "2024" pa en farsk
gradde) vilket kan trigga falska "utgangen"-varningar. Tva lager:
- Prompt: modellen far aldrig gissa artal, returnerar null vid tvetydiga/
kryptiska koder (buildFridgePrompt + buildExpiryPrompt).
- Kod: ny isPlausibleFoodDate() nollar orimligt gamla/framtida datum i
toDetectedItems. Hellre inget datum an ett felaktigt (spec §13).
promptVersion -> gemini-fridge-v2. Tester 7/7 grona.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZdew6cWn1MeHqoYWFfxzo
BUG: forseglad vara utan tryckt datum fick fabricerat utgang (purchasedAt + shelfLifeGuidance, som ar hallbarhet EFTER oppning) -> falska 'gar ut snart'-varningar OCH gav sken av att datum inte lastes. Nu: ingen data -> unknown (hedrar appens egen princip 'aldrig gissa'). parseDate laser aven YY-MM-DD/YYMMDD/YYYYMMDD (svenska stamplar) som forr slangdes. Regressionstester tillagda. 36/36 gront.
TRIAL_DAYS var redan 14 i koden men auth.trialNote (12 sprak), butiksmetadata, juridik-utkast, API-ref, exec-summary och UX-doc sa 7. Nu 14 overallt. Rorde EJ icke-trial 7-dagar (inbjudningslank, backup, S3-lifecycle, grace, retention). Beslut: Johan (battre onboarding).
Koden gav 5 men paywall-copy (12 sprak), butiksmetadata (docs/22) och subscriptions-testet sager 10. Enforcement (canUseAiScan) laser konstanten dynamiskt sa en rad racker. Beslut bekraftat av Johan: free=10.
customNodeFetch previously used res.setEncoding('utf8') and concatenated
chunks into a string. This corrupted JPEG/PNG binary data with UTF-8
replacement characters, causing Gemini to return:
400 Unable to process input image.
Now chunks are collected as Buffers and concatenated, preserving binary
integrity when images are fetched from presigned S3 URLs before being
sent to Gemini.