# AMOS Development Workcamp 2026 # Volume 6: Lessons Learned and Continuous Improvement # Period: 2026-06-04 – 2026-06-07 (intensiv fas) # Genererat: 2026-06-07 | Klassifikation: INTERN – KONFIDENTIELL --- ## INLEDNING Denna volym dokumenterar incidenter, rotorsaksanalyser (5 Why), förbättringar (Kaizen-register) och lärdomar från AMOS Workcamp 2026. Målet är att nästa workcamp inte upprepar samma misstag. Claude × Siemens-linsen gäller för detta dokument: var incident dokumenteras ärligt, inklusive obekväma fynd. "Surface:a verkliga fynd (även obekväma)" – Claude-sidan av beslutslinsen. --- ## AVSNITT 1: INCIDENTANALYS – 5 WHY ### INCIDENT 1: LandveX = bostad-incidenten **Symptom:** ESLM (ALETHEIA i test) och produktionschatten (`/api/aamos/chat`) svarade att LandveX säljer bostäder. Gravt faktafel med potentiell kundpåverkan om det gått live. **Tidpunkt:** Upptäckt 2026-06-06 under systematisk systemkunskaps-härdning. **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför svarade AI att LandveX säljer bostäder? | Produktionschatten hade ingen aktuell LandveX-definition. | | 2 | Varför saknade chatten korrekt definition? | `/api/aamos/chat` anropade `getEnrichedPrompt()` → `getFactsContext()` → hårdkodad `wavult-facts.mjs`. Den filen hade LandveX-def som proptech/fastighet. | | 3 | Varför hade `wavult-facts.mjs` fel definition? | Ingen process för att hålla filen synkad med kanonisk AAMOS_CANON.md. Filen skrevs manuellt vid ett tidigt skede och uppdaterades aldrig. | | 4 | Varför fanns det 39 konkurrerande truth-filer? | Ingen utsedd kanonisk sanningskälla. Varje session/feature kunde skapa en ny "truth"-fil. | | 5 | Varför saknade RAG en kanonisk källa? | RAG-index skapades ad-hoc, läste bara 3 filer, och RAG-stubs svarade `ok:true` även när index var tomt – felet doldes. | **Rotorsak:** Avsaknad av en enda kanonisk sanningskälla + stubs som dolde att systemet var trasigt. **Åtgärder vidtagna:** - Skapade `/opt/amos/data/AAMOS_CANON.md` (ENDA kanoniska sanningskällan, E4-klassad) - Patchade `rag.mjs` (CANON tier-1, alltid läst) - Byggde om RAG-index (94 chunks) - Rättade `wavult-facts.mjs` med korrekt LandveX-definition - Ändrade `LOCKED RULES` i produktionschatten (fakta alltid-injicerad) - Neutraliserade bostad-orphan (`landvex-landing.html` → redirect) - Arkiverade 8 dubblett-truth-filer **Verifierat resultat:** "Säljer LandveX bostäder?" → AI: "Nej... infrastrukturkontroll." HTTP 200. **Lärdom för nästa workcamp:** > En enda CANON-fil är bättre än tio semi-korrekta truth-filer. Stubs ska ALDRIG svara `ok:true` på > tomma svar – det döljer att systemet är trasigt. --- ### INCIDENT 2: OOM-kraschen via SocialAuto restart-storm (2026-06-05) **Symptom:** Alla domäner mot port 3100 gav timeout (000). amos-core nådde 5.2GB/6.0GB RAM, 1850 aktiva tasks, NATS 503-flood. Systemet var i praktiken nere. **Tidpunkt:** 2026-06-05 (exakt tid ej loggad i dagbok, men under nattens arbete). **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför kraschade amos-core med OOM? | 5.2GB RAM → 6.0GB limit. Systemet hade 1850 tasks. | | 2 | Varför var det 1850 tasks? | 137 parallella Chromium-instanser (stealth-mode) körde simultaneously, vardera ~100MB. | | 3 | Varför körde 137 Chromium-instanser? | SocialAuto (apifly job-posting, `social-account-automation.mjs`) relanserade ALLA queued/failed-jobb vid varje omstart – utan concurrency-tak. | | 4 | Varför relanserades alla jobb vid omstart? | Kod saknade global semafor/concurrency-limit. Vid restart = ny storm av parallella Chromium-launches. | | 5 | Varför fanns ingen concurrency-limit? | Funktionen byggdes utan att ta hänsyn till restart-scenariot. Ingen review av resursförbrukning per job. | **Rotorsak:** SocialAuto's restart-beteende (amplifiering: varje omstart = ny storm) kombinerat med avsaknad av global concurrency-begränsning. **Åtgärder vidtagna:** 1. Cancellerade 274 skenande jobb i `/opt/amos/data/social-account-jobs.json` 2. PATCH: global semafor `SOCIALAUTO_MAX_CONCURRENT=3` runt `runAutomation()`, wrapper `_runAutomationCore` **Verifierat resultat:** amos-core 200, 1.7GB RAM, load 2.0. Stabilt. **Diagnostisk lärdom:** > Vid amos-core-strul: kolla ALLTID `pgrep -fc chrome` och `social-account-jobs.json` status-counts FÖRST. > Restart utan att cancellera jobb förvärrar situationen. --- ### INCIDENT 3: Provider-kredithaveri (xAI/Grok, 2026-06-04) **Symptom:** Grok/xAI tog slut på krediter mitt i en orkestrering. Erik beskrev det som "generalhaveri". Orkestreringen kunde inte slutföras. Allt som förlitade sig på Grok som provider blockerades. **Tidpunkt:** 2026-06-04 under dagsarbete. **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför havererade orkestreringen? | Grok/xAI-kontot var tomt på krediter. | | 2 | Varför var kontot tomt utan förvarning? | Ingen kredit-monitor för xAI-kontot. | | 3 | Varför saknades kredit-monitor? | Varje provider behandlades manuellt. Ingen systemisk kreditövervakning. | | 4 | Varför saknades systemisk kreditövervakning? | AI-gateway (som byggdes natten efter) existerade inte ännu. | | 5 | Varför byggdes inte AI-gateway tidigare? | Multi-provider failover var inte prioriterat tills haveriet bevisade behovet. | **Rotorsak:** Avsaknad av proaktiv kreditövervakning och automatisk failover. **Åtgärder vidtagna (natten 2026-06-04 → 06-05):** - Byggde AI-gateway (`/opt/amos/data/ai-gateway/gateway.mjs`, port 3270, PM2) - 6 providers med auto-failover + circuit-breaker - FAILOVER BEVISAD LIVE (trasig provider → groq, 1 hopp) - Provider-monitor (`monitor.mjs`, PM2): pollar 7 providers var 5:e min - Auto-larm CRITICAL till Winston (kredit) och Johan (nedtid) via HomoDeus - Tickets utfärdade: Johan PROV-001..006, Winston PROV-W1..6 - Grok exkluderades från gateway tills påfylld **Absolut regel (Erik, CAPS):** > "ALDRIG I PRODUKTION. VARJE PROVIDER: PRIMÄRT REVOLUT + FALLBACK ANNAN BANK + AUTO-TOPUP + BUFFERT." **Ansvarig framåt:** - Johan/Sven: teknisk setup/monitor/failover - Winston/Rufus: kort/konton/påfyllning --- ### INCIDENT 4: Leon/Vincento-kontaminering av träningsdata (2026-06-06) **Symptom:** v3 och v4 av ESLM-träningsdata innehöll 90+129 Leon/Vincento-referenser (train) och 17+18 (validation). Modellen lärde sig en simulerad persona som aldrig existerat. Träningen stoppades. **Tidpunkt:** Upptäckt 2026-06-06 22:18 efter Eriks klargörande att Leon = simulering. **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför var träningsdata kontaminerad med Leon/Vincento? | Varje träningsexempel hade AAMOS-systemets kontext i system-prompten, inklusive team-mappning med Leon. | | 2 | Varför fanns Leon i system-prompten? | Leon behandlades som verklig anställd i alla systemfiler. Ingen markering som simulering. | | 3 | Varför behandlades Leon som verklig? | Ingen kontroll av personas mot HR-register. Leon hade e-post, agent-mappning, payroll-post (EMP-004) och kodade roller. | | 4 | Varför hade en simulering alla verkliga attribut? | Simuleringen designades för realism – men ingen distinktion skapades mellan "simulerad test-persona" och "verklig anställd". | | 5 | Varför saknades distinktionen? | Systemet hade ingen metadata-tagg för simulerade vs. verkliga entiteter. | **Rotorsak:** Avsaknad av entitetstyp-distinktion (simulerad vs. verklig) i systemet, kombinerat med att Leon hade alla attribut av en verklig anställd (e-post, payroll, kod-routing, agent). **Åtgärder vidtagna:** - v3 och v4 kasserades omedelbart - v5 skapades: droppade 12 371 train + 1 357 val företagsspecifika exempel - ALLA system-prompts byttes mot neutral generell ("evidensbaserad assistent för verksamhetsdrift") - 3 parallella purge-agenter kördes (purge1_api, purge2_data, purge3_scripts) - EMP-004 "Leon Magnusson" (alias för Leon Russo, samma syntetiska pnr) raderades ur payroll/HR - Slutkoll: Leon Russo=0, Leon Magnusson=0, vincento=0, 900510-3456=0 i aktiv kod **Effekt på arkitektur:** Incidenten ledde direkt till principen **Separation of weights & facts** (SD-003): > "Modellen bär ALDRIG företagsdetalj. Fakta injiceras via MNEMOSYNE vid runtime." --- ### INCIDENT 5: JWT Algorithm Confusion (CVSS 10.0) – Identifierad och åtgärdad 2026-05-08 **Symptom:** Alla `authMiddleware`-instanser använde `jwt.decode()` istället för `jwt.verify()`. Vem som helst kunde förfalska admin-JWT utan att känna till secret. **Tidpunkt:** 2026-05-08 under red-team/hardening-arbete. **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför kunde JWT:er förfalskas? | `jwt.decode()` verifierar INTE signaturen – bara decodes base64. | | 2 | Varför användes `jwt.decode()` istället för `jwt.verify()`? | Förväxling av metodnamn/syfte vid initial implementation. | | 3 | Varför spreds felet till 6 filer? | Copy-paste av auth-middleware utan review. Ingen centraliserad auth-hjälpfunktion. | | 4 | Varför fångades det inte i review? | Ingen security review-process eller automatiserad SAST (static analysis). | | 5 | Varför saknades security review? | Arbetstempon under byggfasen prioriterade features före säkerhetsreviews. | **Rotorsak:** Copy-paste + avsaknad av centraliserad auth-hjälpfunktion + ingen security review. **Åtgärder:** Fixad i 6 filer. `alg:none`-attack blockerad. Rate limiting, security headers, input validation tillagda. --- ### INCIDENT 6: Kafka-backbone degraderad i 8 dagar (2026-06-07) **Symptom:** Kafka-klustret (3-broker KRaft StatefulSet) körde i degraderat läge med 2/3 brokers i 8 dagar utan att det uppmärksammades. kafka-1 saknades. **Tidpunkt:** Upptäckt 2026-06-07 14:45 under infrastrukturinventering. **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför körde Kafka med 2/3 brokers? | kafka-1 kunde ej skapas pga ResourceQuota-blockering och borttagen EBS-volym. | | 2 | Varför blockerade ResourceQuota? | init-container `fix-volume` saknade resource limits → `wavult-quota` blockerade (FailedCreate ×721 över 8 dagar). | | 3 | Varför var EBS-volymen borttagen? | kafka-1:s PVC var bunden till vol-0891ca1531dc90def som raderats (InvalidVolume.NotFound). | | 4 | Varför uppmärksammades det inte? | Ingen monitoring av Kafka broker-hälsa. Degraderat läge genererade inga larm. | | 5 | Varför saknades Kafka-monitoring? | Observability-gap. Fokus på app-hälsa, ej backbone-hälsa. | **Rotorsak:** Avsaknad av Kafka broker-hälsoövervakning. 8 dagar = oacceptabelt för produktionsbackbone. **Åtgärder:** - Patchade init-container med resource limits (25m/64Mi requests, 100m/128Mi limits) - Raderade orphaned PVC → EBS-CSI provisionerade ny 20Gi gp3 - Broker rejoinade via replikation (RF=3 tålde det) - Rolling restart av hela STS - **RESULTAT:** 3/3 brokers Running, 0 under-replicated partitions, ISR fullständig --- ### INCIDENT 7: host-2 DNS-beroende på Tailscale MagicDNS **Symptom:** host-2 (AMI-klon av server-2) kunde inte resolva RDS-DNS och gav ENOTFOUND. `/health/ready` = DEGRADED. Hade registrerats i target group (tur att djup health-check stoppade det). **Tidpunkt:** 2026-06-05 02:38–03:09 UTC. **5 Why-analys:** | Nivå | Varför? | Svar | |------|---------|------| | 1 | Varför kunde inte host-2 resolva RDS? | `/etc/resolv.conf` pekade på 100.100.100.100 (Tailscale MagicDNS). host-2 hade ingen Tailscale. | | 2 | Varför pekade resolv.conf på Tailscale? | AMI skapades från server-2 som kör Tailscale. Statisk resolv.conf kopierades. | | 3 | Varför använder server-2 Tailscale som primär DNS? | Tailscale MagicDNS installerades tidigt för dev-convenience och ersatte VPC-resolver. | | 4 | Varför byggdes ingen DNS-resiliens in? | Ingen policy för DNS-konfiguration på prod-hostar. | | 5 | Varför saknades DNS-policy? | Det fungerade på server-2 – problemet syntes bara vid skalning till ytterligare host. | **Rotorsak:** Prod-DB-resolution beroende av Tailscale. Ej synligt på en host, kritiskt på två. **Åtgärder:** - host-2 v2: user-data skriver `/etc/resolv.conf` → nameserver 172.31.0.2 (VPC-resolver) + `chattr +i` - server-2: systemd-resolved drop-in `/etc/systemd/resolved.conf.d/99-vpc-fallback.conf` (FallbackDNS=172.31.0.2) - **ALB-lärdom:** Deep health-check (`/health/ready` med DB-check) förhindrade att degraderad host fick trafik. --- ## AVSNITT 2: KAIZEN-REGISTER Kaizen = kontinuerliga förbättringar som identifierades och genomfördes under workcampet. ### K-001: env-preload.mjs löser ESM-import-ordningsproblematik **Problem:** Stripe och APNS lästes vid ESM-import-tid (rad 11) FÖRE env-loadern (rad 34+) → låstes i MOCK_MODE. **Förbättring:** `env-preload.mjs` importeras som ALLRA FÖRSTA rad i `index.mjs` – laddas hela env-filen innan någon route-import. **Effekt:** End-to-end Stripe-session skapad (cs_test_…). Inga kodändringar vid sk_live_-switch. ### K-002: ALB health-check → /health/ready (djup, DB-check) **Problem:** ALB health-check mot `/health` (liveness) = process up men ej DB. En degraderad host fick trafik. **Förbättring:** Health-check ändrad till `/health/ready` som gör faktisk DB-round-trip. **Effekt:** host-2 (ENOTFOUND på RDS) hölls automatiskt utanför rotation. Self-protecting arkitektur. ### K-003: Idempotent Stripe-webhook med processed_stripe_events-tabell **Problem:** Dubbel webhook (Stripe-retry ELLER 2 hosts) → dubbel kreditering möjlig. **Förbättring:** Ny tabell `quixzoom.processed_stripe_events` (event_id PK), `INSERT ON CONFLICT DO NOTHING` + atomisk `balance = balance + credits`. **Effekt:** Dubbel-kreditering matematiskt omöjlig oavsett antal hostar eller Stripe-retries. ### K-004: Concurrent-tak för SocialAuto (SOCIALAUTO_MAX_CONCURRENT=3) **Problem:** SocialAuto relanserade alla queued jobs vid restart utan tak → OOM. **Förbättring:** Global semafor runt `runAutomation()`, wrapper `_runAutomationCore`. **Effekt:** Max 3 Chromium-instanser simultant. Restart = ingen storm. ### K-005: AI-gateway med auto-failover (circuit-breaker) **Problem:** En provider (Grok) tar slut → hela orkestreringen havererar. **Förbättring:** AI-gateway med 6 providers, task-kedjor (reasoning/fast/search/creative/financial/default), circuit-breaker. **Effekt:** FAILOVER BEVISAD LIVE: trasig provider → groq, 1 hopp, 0 avbrott i orkestrering. ### K-006: Provider-monitor var 5:e minut med auto-larm **Problem:** Ingen visste att xAI/Grok var tomt förrän orkestrering havererade. **Förbättring:** `monitor.mjs` (PM2) pollar 7 providers var 5:e min. Auto-larm CRITICAL till Winston (kredit) och Johan (nedtid) via HomoDeus. **Effekt:** Reaktiv → proaktiv kreditövervakning. ### K-007: AAMOS_CANON.md som enda kanonisk sanningskälla **Problem:** 39 konkurrerande truth-filer → LandveX=bostad-incidenten. **Förbättring:** En enda CANON-fil (E4), tier-1 i RAG, alltid-injicerad i produktionschat. **Effekt:** Systemet svarar korrekt om LandveX. Fakta uppdateras på ett ställe. ### K-008: Stub-transparens (X-AAMOS-Stub header + Warning + _stub:true) **Problem:** 432 stubs svarade `ok:true` på tomma svar → dolde att subsystem var döda. **Förbättring:** Varje stub-träff loggas + `X-AAMOS-Stub:true` + `Warning`-header + `_stub:true` i body + ny `/api/_stub-report`. **Effekt:** Konfigurerad förmåga som ej är ansluten syns nu i instrumenteringen. ### K-009: SSM Run Command för root-operationer (nginx/systemd utan sudo-beroende) **Problem:** nginx-filer ägdes av root/ec2-user → bernt kunde ej skriva → blockerade nginx-tickets till Johan. **Förbättring:** AWS SSM Run Command via IAM-roll `platform-ec2-ssm-role`. Mönster: `aws ssm send-command --document AWS-RunShellScript`, base64-encoda komplexa script. **Effekt:** Kan nu ändra nginx, systemd, certs via SSM. Inga fler "väntar på Johan för root"-blockeringar. ### K-010: LLM-as-judge med 4-lagers fallback **Problem:** Keyword-matchning för svenska för trubbig. Qwen-32B som domare för svag (trodde "PASS" = EU-direktiv). **Förbättring:** Judge-v2: Bedrock-Opus-4-6 → Sonnet-4-5 → direkt-Opus-4-8 → Qwen-235B. LLM-schema-agnostisk parser. **Effekt:** En poliskontroll är nu aldrig svagare än det den vaktar. ### K-011: Separation of weights & facts (arkitekturprincip) **Problem:** Företagsdetaljer inbränt i modellvikter = säkerhetsrisk, kräver omträning vid ändring. **Förbättring:** ALETHEIA (modellvikter) = generell evidensmotor. MNEMOSYNE (CANON/RAG) = runtime-fakta. **Effekt:** Ingen faktaläcka via vikter. Fakta ändras utan omträning. ESLM säljbar generellt. ### K-012: POS→Ledger automatisk bokföring (idempotent) **Problem:** Restaurangförsäljning postades ej automatiskt till aamos-ledger → SIE4 var tom. **Förbättring:** `POST /pos/ledger/post-day {fecha}` + cron 03:15 Europe/Madrid. Tracking-tabell `restaurant_ledger_postings` (UNIQUE tenant+datum). Idempotent. **Effekt:** "Säljer jag en paella, hamnar den i böckerna?" = JA. Automatiskt, utan handpåläggning. ### K-013: Ticket-system för felrapportering (aamos-restaurant-tickets:3318) **Problem:** Ingen strukturerad väg för restaurangtjänster att rapportera integrationsproblem. **Förbättring:** Ny Rust/axum-tjänst med severity (low/medium/high/critical), status-flöde, källa (staff/system/customer/agent), HTML-dashboard. **Effekt:** POS auto-skapar high-severity accounting-ticket när ledger-postning failar. Systemintelligens istället för stum kraschtystnad. ### K-014: Webhook-idempotens som förutsättning för multi-host **Problem:** Multi-host (host-2) blockerades av att Stripe-webhooks ej var idempotenta. **Förbättring:** Löstes som prerequisite för RES-004. Multi-host + idempotens = sann redundans. **Effekt:** Systemet är nu multi-host-redo utan risk för ekonomisk data-korruption. ### K-015: Jurisdiktionsmedveten onboarding (ES/SE och fler) **Problem:** Onboarding-tjänst hårdkodad för Sverige → spansk CIF och IVA-satser avvisades. **Förbättring:** `country` (ISO-3166, default "SE") i register + DB-kolumn. ES→CIF/NIF + IVA {4,10,21}, SE→orgnr + moms {12,25}. **Effekt:** Spansk chiringuito kan slutföra alla 7 onboarding-steg. Global skalning möjlig. ### K-016: Gravation arm64/Graviton-only för EKS (deterministisk flotta) **Problem:** Preferred (80/20 arm64/x86-fallback) lämnar en variabel som kan överraska i prod. **Förbättring:** Required arm64-only (nodeSelector + requiredDuringScheduling). Alla images: `--platform linux/arm64`. **Effekt:** Homogen flotta, reproducerbart beteende, ~20% billigare. Inga edge-cases från mixed architectures. ### K-017: Django E2E-simuleringen (986 orders, €146.5k, 24/24 OK) **Problem:** Restaurang-stacken hade 6 oupptäckta integrationsbuggar (VAT overflow, analytics-paths, decimal-parsing, etc.). **Förbättring:** Fullständig månads-driftsimulering med 986 orders, 15 tjänster, ~130 endpoints, 14 verifieringsfaser. **Effekt:** Alla 6 buggar hittades och fixades. SIE4-kedjeavstämning POS→Modelo303→Ledger→SIE4 perfekt. --- ## AVSNITT 3: TEKNISKA LÄRDOMAR ### TL-001: Verifiera ALLTID den körande filen, inte filen på disk **Källa:** Produktionschat-fix (2026-06-06) > Körande `amos-core` = `services/amos-core/server.mjs`. `scripts/server.mjs` KÖRS INTE. > Hade nära håll på att fixa fel fil. Kontrollera alltid med `ps aux` eller `systemctl status`. ### TL-002: Stubs som svarar ok:true döljer döda subsystem **Källa:** LandveX-incidenten + 432 stubs-audit (2026-06-06) > Instrumentering ska visa sanningen, inte dölja den. En stub som svarar `ok:true` på tom respons är > aktivt skadlig – det ger en falsk bild av systemhälsan. ### TL-003: ESM import-ordning är deterministisk och kan bita **Källa:** Stripe env-preload.mjs fix (2026-06-05) > I ES modules körs importerade moduler vid import-tid, inte vid runtime. Variabler som läses tidigt > (t.ex. env-variabler) måste finnas INNAN importen. Lösning: preload-modul som allra första import. ### TL-004: AMI-kloning kopierar statisk konfiguration inklusive resolver **Källa:** host-2 DNS-incidenten (2026-06-05) > AMI-snapshot fryser in all konfiguration inklusive `/etc/resolv.conf`. Om produktionsmiljön beror > på ett sidoverktyg (Tailscale) som inte finns på alla hostar, sprids beroendet vid kloning. > Lösning: user-data-script som skriver DNS-konfiguration vid boot. ### TL-005: `pgrep -fc chrome` är första diagnostiksteg vid amos-core-strul **Källa:** OOM-incidenten (2026-06-05) > Kolla antalet Chromium-instanser och social-account-jobs.json status-counts INNAN restart. > Restart utan job-avbrottning förvärrar storm-beteende exponentiellt. ### TL-006: LLM-as-judge måste vara starkare än det den poliskontrollerar **Källa:** ESLM red-team, judge-evolution (2026-06-06) > Qwen-32B som domare klassade "PASS" som ett EU-direktiv och godkände felaktiga svar. > En poliskontroll som är svagare än systemet den granskar ger falsk säkerhet. > Regel: judge-modellen ska ALLTID vara starkare än production-modellen. ### TL-007: Keyword-matchning för svenska är för trubbig som red-team **Källa:** ESLM red-team v1 vs v2 (2026-06-06) > Keyword-matchning fångade inte subtila felaktigheter i svenska svar. Ersattes av LLM-as-judge (v2). > Lärdom: för komplexa domäner krävs semantisk bedömning, inte mönstermatchning. ### TL-008: `gpt-5.5-pro` kräver `/v1/responses`, ej `/chat/completions` **Källa:** Infra-fakta 2026-06-05 > OpenAI:s nya API-endpoint är inte bakåtkompatibel. Mycket långsam (>20 min öppna promptar). > Undvik för tidskänsliga körningar. ### TL-009: sqlx compile-time-makron (`query!`) kräver live DATABASE_URL vid build-tid **Källa:** EKS-migration compliance-tjänst (2026-06-07) > 14/15 Rust-tjänster byggde direkt. Compliance: enda med `query!`-makron → krasch utan DATABASE_URL. > Lösning: `--build-arg DATABASE_URL` vid Docker build. Alternativt: använd `query()` (runtime) istället. ### TL-010: ResourceQuota blockerar pod-skapande tyst (FailedCreate-events) **Källa:** Kafka-degraderingen (2026-06-07) > kafka-1 fick FailedCreate ×721 utan larm. ResourceQuota stoppade init-containern pga saknade resource limits. > Lärdom: Resource limits ska finnas på ALLA init-containers. Övervaka FailedCreate-events. ### TL-011: RDS SSL-konfiguration krävs i Node.js-connections mot AWS RDS **Källa:** tool-registry SSL-fix (2026-06-05) > `new Pool({connectionString: AMOS_DB_URL})` utan SSL-config → RDS avvisade med "no pg_hba.conf entry". > Lösning: `ssl: {rejectUnauthorized: false}` i Pool-konfiguration. ### TL-012: Providermodellnamn förändras – håll dem uppdaterade **Källa:** Gemini 2.0→2.5 fix (2026-06-05) > Gamla modellnamn (Gemini 2.0, gammal Haiku) kraschade tyst. Orsakade dold instabilitet i orkestrering. > Lärdom: API-modellnamn är ej stabila – håll en provider-modell-förteckning uppdaterad. --- ## AVSNITT 4: PROCESSLÄRDOMAR ### PL-001: Parallellisering med tickets och subagenter är kraftfullt **Källa:** 2026-06-06 parallellbygge (14 tickets, 4 epics, 8 subagenter) > 90/100 tickets lösta på en session. Erikmönstret: "gör tickets, starta agenter." Fungerar för > parallella epics som inte delar state. Kräver tydlig tickets-struktur och agent-scope. ### PL-002: Red-team FÖRE promotion är inte valfritt **Källa:** ESLM-processen (2026-06-06) > ALETHEIA-baslinjen: 33% passerade, 5 kritiska brister. Utan red-team hade modellen gått live med > LandveX=bostad och hallucinerande org-nr. Red-team är minimikravet, inte ett bonus-steg. ### PL-003: Ekonomifunktionen måste ha proaktiv förvarning **Källa:** xAI/Grok-haveriet (2026-06-04) > Reaktiv hantering (Erik ringer Winston när Grok är tomt) är oacceptabelt. Systemet måste larma > INNAN kontot är tomt. Auto-topup + buffert + 5-min kreditkoll är miniminivå. ### PL-004: Kör simuleringen INNAN du berättar för kunden att det är redo **Källa:** Restaurang-plattformens 6-buggars-fynd (2026-06-07) > Erik trodde restaurang-stacken var "100% redo för onboarding". E2E-test avslöjade BLOCKER (spansk CIF). > Lärdom: "100% redo" valideras av systemet, inte av en persons uppskattning. Kör alltid simulering. ### PL-005: Behörighetshierarkier ska tydliggöras i agentmailboxen **Källa:** Beroende av Johan för nginx (2026-06-04/05) > Bernt (bernt-user) kan ej skriva nginx-filer (root/ec2-user). Blockade i veckor tills SSM-mönstret > upptäcktes. Lärdom: dokumentera åtkomstgränser och eskaleringsvägar tydligt från start. ### PL-006: Kanoniska namn ska låsas tidigt, inte sent **Källa:** Hermes→Hephaistos-omdöpning (2026-06-07) > Hermes behövde döpas om (76 filer) pga namnkollision med externa bibliotek i träningsdata. > Lärdom: namnkonflikter med populära bibliotek är dyrare att fixa sent. Välj ovanliga egennamn. --- ## AVSNITT 5: ARKITEKTURLÄRDOMAR ### AL-001: Separation of concerns gäller även AI-modeller **Källa:** ESLM-arkitektur, SD-003 (2026-06-06) > Modellvikter (ALETHEIA) och faktabas (MNEMOSYNE) är separata ansvarsområden, precis som > kod och konfiguration. En modell som bär konfiguration (företagsfakta) är svår att uppdatera. ### AL-002: Event-backbone (Kafka) ska väljas och övervaka från dag 1 **Källa:** Kafka-degraderingen 8 dagar (2026-06-07) > Tre parallella event-mekanismer (Kafka, aamos-event-bus, NATS/Redis) skapade oklarheter. > Kafka var productionstanken men 2/3 brokers – utan larm i 8 dagar. Välj en backbone, övervaka den. ### AL-003: Gitops + EKS + ExternalSecrets är rätt mönster (Siemens-standard) **Källa:** EKS-migration referensmönster (2026-06-07) > ArgoCD + external-secrets + ClusterSecretStore + AWS SSM = reproducerbar, auditbar deploy. > Varje workload: ExternalSecret → Deployment → Service → Kong-route. Mönstret verifierades end-to-end. ### AL-004: Single point of truth gäller all systemkunskap **Källa:** LandveX-incidenten (2026-06-06) > 39 competing truth-filer → inkonsistens. AAMOS_CANON.md som enda E4-fil löste grundproblemet. > Samma princip gäller all systemkunskap: en CANON, alla vet var de hittar sanningen. ### AL-005: Health-check-djup avgör om redundansen fungerar på riktigt **Källa:** host-2 DNS-incidenten (2026-06-05) > `/health` (liveness) = process up, men ej nödvändigtvis fungerande. `/health/ready` (readiness) med > faktisk DB-round-trip är minimikravet för ALB-integrering. Ytlig health = falsk trygghet. ### AL-006: Multi-AZ är grundkrav, inte lyx **Källa:** RES-001/003 (2026-06-05) > Single-AZ RDS: RTO = timmar. Multi-AZ: RTO 60–120s. Diff = $700/mån. Erik: "Vi har inte alternativ." > Lärdom: bygg multi-AZ från start. Eftermontage är dyrare (maintenance window, DNS-propagation). ### AL-007: Idempotens är förutsättning för horisontell skalning **Källa:** Stripe-webhook-idempotens som Fas-2-prerequisite (2026-06-05) > Kan inte lägga till fler hostar utan idempotenta webhooks. Idempotens är inte ett nice-to-have – > det är det som gör horisontell skalning säker. --- ## AVSNITT 6: ERKÄNDANDEN ### Vad gick riktigt bra? 1. **Parallellisering med subagenter** – 90/100 tickets på en session bevisar att multi-agent-koordination fungerar. 2. **Deep health-check räddade produktionen** – host-2 med trasig DNS-resolution fick aldrig trafik tack vare `/health/ready`. 3. **Red-team-grinden fångade kritiska brister** – utan red-team hade LandveX=bostad gått live. 4. **SSM-mönstret löste root-beroendet** – månaders blockering av nginx-filer löst på en timme. 5. **EKS-migrationen gick smidigt** – 17 tjänster, 34 pods, alla på Graviton/arm64, alla friska. 6. **DDP-träningen fungerade** – från ~8h på A10G till ~1h på 8x A100. Ny hastighetstandard. 7. **Restaurang E2E-simulering** – hittade 6 riktiga integrationsbuggar och kvantifierade dem till öret. ### Vad var svårast? 1. **Leon/Vincento-purgen** – kräver precision (behåll andra Leons, radera bara rätt entiteter). 3 agenter parallellt krävdes. 2. **Kafka-degraderingen** – 8 dagar utan larm är ett allvarligt observability-gap. Fixades men borde ha fångats dag 1. 3. **Judge-modell-valet** – det tog tre iterationer (keyword → Qwen-32B → Opus-direkt) för att hitta rätt domar-nivå. 4. **Providermodell-avvecklingen** – gamla modellnamn kraschade tyst. Svårt att spåra utan centraliserad provider-förteckning. --- *Volym 6 av 7 | AMOS Workcamp 2026 | Klassifikation: INTERN – KONFIDENTIELL* *Nästa: VOL7-AMOS-Operating-System.md*