Gå til innholdet

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

  • Document får nytt felt ingestion_status
  • Spec 007 opprettes for Ingestion Engine
  • apps/api/src/ingestion/ modul legges til monorepo-strukturen
  • pg-boss legges 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:

  1. Fjerne fritekst-feltet dependencies fra ImprovementIdea
  2. Legge til ny ImprovementDependency-junction-tabell med strukturert dependency_type
  3. ImprovementIdea fungerer som “prosjekt” for større tiltak via kobling til Tasks og andre idéer

Begrunnelse

  • Project i forslaget var nesten identisk med ImprovementIdea — duplikat-problem
  • Å innføre en ny entitet ville kreve svar på: “Hva er forskjellen på et Project og en ImprovementIdea?”
  • ImprovementDependency gir den strukturerte avhengighetsmodelleringen som B20/B21 krever
  • Simpler modell er enklere å vedlikeholde og forklare til AI-assistenten

Konsekvenser

  • ImprovementIdea.dependencies (fritekst) fjernes — erstattes av ImprovementDependency
  • 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:

  1. Utvide InteriorAsset med feltene price_nok, fits_room, matches_design
  2. InteriorAsset med status=considering er “produktkandidat”
  3. ProductReference (enkel lenkestump) beholdes for ustrukturerte referanser
  4. ShoppingTracker (prissporing) utsettes til Post-MVP og behandles separat

Begrunnelse

  • Tre overlappende entiteter (ProductReference, InteriorAsset, ProductCandidate) ville gitt tvetydig livssyklus og duplisert data
  • InteriorAsset med status=considering er allerede en “produktkandidat” — bare mangler noen evalueringsfelt
  • Livssyklusen blir tydelig: considering → owned/removed/planned
  • Enklere for AI-assistenten å arbeide med én entitetstype

Konsekvenser

  • InteriorAsset får nye felt: price_nok, fits_room, matches_design
  • room_id gjøres nullable — en vurdert sofa trenger ikke rom-tilknytning ennå
  • ShoppingTracker (prissporing med cron-jobb) er Post-MVP og ikke en del av MVP-scope
  • LightingPlan (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.