decision-log
Dette dokumentet er auto-synket fra kildefilene i boligassistent-repoet. Endringer her vil overskrives ved neste sync. Rediger kildefilen direkte.
ADR-010: Ingestion Engine — design av onboarding-pipeline
Section titled “ADR-010: Ingestion Engine — design av onboarding-pipeline”Dato: 2026-03-17 Status: Besluttet
Kontekst
Brukerbehov B22–B27 beskriver et onboarding-behov: bruker laster opp salgsoppgave og
takstrapport, AI ekstraherer strukturerte data, bruker godkjenner før noe lagres.
Dokumentet “Brukerbehov ved oppstart” foreslo fire nye entiteter:
SourceDocument, ExtractionJob, ExtractedFact, ReviewItem.
Beslutninger
1. Ikke opprette SourceDocument — bruk eksisterende Document
Document finnes allerede med doc_type: takstrapport/salgsoppgave. Å lage en ny
SourceDocument-entitet ville skapt to overlappende “dokument”-konsepter.
I stedet: legg til ingestion_status-felt på Document.
2. ReviewItem slås inn i ExtractedFact
ReviewItem hadde kun to felt (extracted_fact, user_action). Disse legges direkte
på ExtractedFact (user_action, user_corrected_value, reviewed_at, reviewed_by).
Enklere skjema, ingen ekstra join, fullstendig audit-trail bevares.
3. ExtractedFact utvides med field_path og suggested_value
Forslaget manglet presisjon om hva faktumet gjelder. field_path (f.eks. rooms[0].area_m2)
og suggested_value (JSONB) gjør det mulig å mappe fakta direkte til entitetsfelter og
bygge en strukturert review-UI.
4. pg-boss som jobbkø — ikke Redis/BullMQ
Asynkron PDF-prosessering krever en jobbkø. pg-boss bruker eksisterende PostgreSQL
og krever ingen ny infrastruktur. BullMQ (Redis) ville lagt til ny tjeneste.
MIT-lisens. Ingen kostnader.
5. Plassering i roadmap: Spec 007, Fase 4 Ingestion Engine bygges etter Spec 001–006 fordi extraction-pipelinen mapper direkte til kjerneentitetene — de må være stabile definert først. Naturlig å bygge parallelt med AI-assistenten da begge bruker Claude API.
Begrunnelse for kritisk designprinsipp «AI foreslår → bruker godkjenner → system lagrer» er ufravikelig fordi:
- AI gjør feil — særlig på norske takstrapporter med ustrukturert layout
- Brukeren må ha tillit til at data er korrekt
- Feil data i kjernemodellen er verre enn ingen data (jf. prioritering i CLAUDE.md)
Kostnadsimplikasjon
Parsing av én takstrapport (60 sider ≈ 80 000 tokens) koster $0.25 ved Sonnet 4.6-priser.
Onboarding med 2–3 dokumenter totalt ≈ $0.50–0.75. Engangsbeløp, godt innenfor
prosjektets kostnadsprofil ($2–10/mnd). Ingen flagg nødvendig.
Konsekvenser
Documentfår nytt feltingestion_status- Spec 007 opprettes for Ingestion Engine
apps/api/src/ingestion/modul legges til monorepo-strukturenpg-bosslegges til som avhengighet (dokumentert i services-and-licensing.md)
ADR-009: ImprovementDependency fremfor separat Project-entitet
Section titled “ADR-009: ImprovementDependency fremfor separat Project-entitet”Dato: 2026-03-17 Status: Besluttet
Kontekst
Brukerbehov B20 (“Kan vi kombinere kjøkken og bad-oppussing?”) og B21 (“Hva bør vi IKKE gjøre nå?”)
krever strukturert modellering av avhengigheter mellom forbedringsprosjekter.
Et utkast (“Forslag utvidelse modell”) foreslo en ny Project-entitet med ProjectDependency.
Beslutning
Ikke innføre en separat Project-entitet. I stedet:
- Fjerne fritekst-feltet
dependenciesfraImprovementIdea - Legge til ny
ImprovementDependency-junction-tabell med strukturertdependency_type ImprovementIdeafungerer som “prosjekt” for større tiltak via kobling til Tasks og andre idéer
Begrunnelse
Projecti forslaget var nesten identisk medImprovementIdea— duplikat-problem- Å innføre en ny entitet ville kreve svar på: “Hva er forskjellen på et Project og en ImprovementIdea?”
ImprovementDependencygir den strukturerte avhengighetsmodelleringen som B20/B21 krever- Simpler modell er enklere å vedlikeholde og forklare til AI-assistenten
Konsekvenser
ImprovementIdea.dependencies(fritekst) fjernes — erstattes avImprovementDependency- Spec 005 (ImprovementIdeas og Tasks) utvides til å inkludere
ImprovementDependency - AI-assistenten kan nå resonere om sekvens og samkjøring basert på strukturerte data
ADR-008: ProductCandidate slås sammen med InteriorAsset(considering)
Section titled “ADR-008: ProductCandidate slås sammen med InteriorAsset(considering)”Dato: 2026-03-17 Status: Besluttet
Kontekst
Brukerbehov B15 og B16 (produktsøk og produktvurdering) krever at systemet kan
evaluere et produkt mot romstørrelse, designretning og eksisterende møbler.
Et utkast (“Forslag utvidelse modell”) foreslo en separat ProductCandidate-entitet
i tillegg til eksisterende InteriorAsset og ProductReference.
Beslutning
Ikke innføre ProductCandidate som separat entitet. I stedet:
- Utvide
InteriorAssetmed felteneprice_nok,fits_room,matches_design InteriorAssetmedstatus=consideringer “produktkandidat”ProductReference(enkel lenkestump) beholdes for ustrukturerte referanserShoppingTracker(prissporing) utsettes til Post-MVP og behandles separat
Begrunnelse
- Tre overlappende entiteter (
ProductReference,InteriorAsset,ProductCandidate) ville gitt tvetydig livssyklus og duplisert data InteriorAssetmedstatus=consideringer allerede en “produktkandidat” — bare mangler noen evalueringsfelt- Livssyklusen blir tydelig: considering → owned/removed/planned
- Enklere for AI-assistenten å arbeide med én entitetstype
Konsekvenser
InteriorAssetfår nye felt:price_nok,fits_room,matches_designroom_idgjøres nullable — en vurdert sofa trenger ikke rom-tilknytning ennåShoppingTracker(prissporing med cron-jobb) er Post-MVP og ikke en del av MVP-scopeLightingPlan(belysningsplanlegging) er Post-MVP — krever Brave Search + LightingPlan-entitet
ADR-001: Relasjonsdatabase (PostgreSQL) fremfor grafdatabase
Section titled “ADR-001: Relasjonsdatabase (PostgreSQL) fremfor grafdatabase”Dato: 2026-03-17 Status: Besluttet
Kontekst Domenemodellen er naturlig en property graph med mange relasjoner på kryss og tvers. Grafdatabaser (Neo4j, Amazon Neptune) ville modellert dette naturlig.
Beslutning Bruke PostgreSQL med fremmednøkler og polymorfiske referanser, ikke en grafdatabase.
Begrunnelse
- PostgreSQL er velprøvd, godt dokumentert og eies av utviklere med SQL-kompetanse
- pgvector gir semantisk søk uten ekstern vector store
- Drizzle ORM gir typesikker tilgang uten overhead
- Relasjonene i dette systemet er ikke så komplekse at graftraversal er nødvendig
- Enklere drift og backup — én database, ikke to systemer
- Grafdatabase kan introduseres senere dersom spørremønsteret krever det
Konsekvenser
Polymorfiske referanser (location_ref_type + location_ref_id) brukes der én entitet
kan peke til flere typer. Dette gir noe svakere databaseintegritet, men er akseptabelt
for dette bruksområdet.
ADR-002: Issue og ImprovementIdea som separate entiteter
Section titled “ADR-002: Issue og ImprovementIdea som separate entiteter”Dato: 2026-03-17 Status: Besluttet
Kontekst Begge entiteter representerer «ting som bør gjøres med boligen». Man kunne modellert dem som én tabell med en type-enum.
Beslutning Holde Issue og ImprovementIdea som helt separate entiteter med separate tabeller.
Begrunnelse
- Issue er et faktum (noe er galt) — ImprovementIdea er et ønske (noe kan bli bedre)
- De har ulike felter: Issue har TG-kode og severity, ImprovementIdea har motivasjon og backlog-status
- Sammenblanding ville gjort prioritering og rapportering vanskeligere
- AI-assistenten trenger å skille mellom «hva er galt» og «hva ønsker vi»
Konsekvenser
Task kan peke til enten et Issue (via source_issue_id) eller en ImprovementIdea
(via source_improvement_id). Begge felter kan være null.
ADR-003: Equipment og InteriorAsset som separate entiteter
Section titled “ADR-003: Equipment og InteriorAsset som separate entiteter”Dato: 2026-03-17 Status: Besluttet
Kontekst Begge er fysiske objekter i et rom. Man kunne brukt én generisk «asset»-tabell.
Beslutning Equipment (teknisk utstyr) og InteriorAsset (møbler, dekor) er separate entiteter.
Begrunnelse
- Equipment tilhører et BuildingSystem og har vedlikeholdsbehov
- InteriorAsset tilhører DesignLayer og har stilattributter
- En varmepumpe og en sofa har fundamentalt ulike datamodeller
- AI-kontekst for «interiørrådgivning» skal ikke inkludere teknisk utstyr
Konsekvenser Ingen. Begge har egne tabeller og egne relasjoner.
ADR-004: DesignDirection som reviderbar, ikke historisk
Section titled “ADR-004: DesignDirection som reviderbar, ikke historisk”Dato: 2026-03-17 Status: Besluttet
Kontekst Designretning endrer seg over tid. Spørsmålet er om man skal bevare historikk (alle versjoner) eller bare nåværende tilstand.
Beslutning
DesignDirection har en status-enum (draft / active / revised / archived) og
updated_at, men ingen full versjonshistorikk i MVP.
Begrunnelse
- Full versjonshistorikk er kompleksitet som ikke gir verdi i MVP
- Status-feltet gir nok kontekst til å forstå at retningen er endret
- Dersom historikk viser seg viktig kan event sourcing legges til senere
Konsekvenser Historikk må dokumenteres manuelt (f.eks. som DecisionNote) dersom det er ønskelig.
ADR-005: Repo-basert prosjektminne og spec-driven development
Section titled “ADR-005: Repo-basert prosjektminne og spec-driven development”Dato: 2026-03-17 Status: Besluttet
Kontekst For å sikre at Claude Code jobber kontrollert og konsistent trengs et system for prosjektminne, specs og arbeidsstyring.
Beslutning Bruke filbasert spec-driven development med dokumenter i repoet som eneste sannhetskilde. CLAUDE.md definerer arbeidsregler. Specs definerer krav. Evaluations dokumenterer verifikasjon.
Begrunnelse
- Claude Code leser filer direkte — filbasert minne er mer pålitelig enn instruksjoner i minnet
- Specs i repoet versjonskontrolleres og kan revideres som kode
- Strukturert arbeidsflyt reduserer risiko for at Claude tar uønskede beslutninger
- Gir brukeren full oversikt og kontroll over hva som implementeres
Konsekvenser Alt arbeid skal gå via spec → task → implementasjon → verifikasjon. Ingen ad-hoc implementasjon uten spec-grunnlag.
ADR-006: Polymorfiske referanser for stedskobling
Section titled “ADR-006: Polymorfiske referanser for stedskobling”Dato: 2026-03-17 Status: Besluttet
Kontekst Mange entiteter (Issue, Observation, Task, SafetyItem) kan knyttes til ulike typer steder: Room, OutdoorSpace, SupportSpace, BuildingSystem. Alternativet er separate fremmednøkkelkolonner for hver type.
Beslutning
Bruke to-kolonne polymorfisk referanse: location_ref_type TEXT + location_ref_id UUID.
Begrunnelse
- Separate fremmednøkler (room_id, outdoor_space_id, …) gir mange nullable kolonner
- Polymorfisk referanse er enklere å lese og vedlikeholde
- Svakhet: ingen databasemessig fremmednøkkel-integritet — løses med applikasjonsvalidering
Konsekvenser
Applikasjonstesting må verifisere at location_ref_id faktisk peker på en eksisterende
entitet av riktig type. Legg til valideringslogikk i service-laget.
ADR-007: pgvector for AI-kontekst fremfor ekstern vector store
Section titled “ADR-007: pgvector for AI-kontekst fremfor ekstern vector store”Dato: 2026-03-17 Status: Besluttet
Kontekst AI-assistenten trenger semantisk søk for å finne relevante entiteter. Alternativer: Pinecone, Weaviate, Qdrant (eksterne tjenester), eller pgvector (PostgreSQL-utvidelse).
Beslutning Bruke pgvector som PostgreSQL-utvidelse.
Begrunnelse
- Holder alt i én database — enklere drift og backup
- Ingen ekstern avhengighet i MVP
- Cosine similarity-søk i pgvector er tilstrekkelig for dette bruksomfanget
- Kan migreres til ekstern vector store later uten store kodeendringer
Konsekvenser
Embeddings lagres som vector(1536) kolonner på relevante tabeller.
Embedding-oppdatering må kjøres ved create og update av relevante entiteter.