210 lines
14 KiB
Markdown
210 lines
14 KiB
Markdown
# VAUCO OS — LEARNINGS.md
|
|
# Eier: OPS-Computer-Hub
|
|
# Format: APPEND-ONLY. Aldri slett, aldri endre eksisterende entries.
|
|
# Sist oppdatert: 2026-06-10 CEST
|
|
|
|
---
|
|
|
|
## Hensikt
|
|
Kodifisert lærdom fra alle sesjoner. Overlever på tvers av tråder og modellbytter.
|
|
Andre tråder kan foreslå append via PR — OPS merger.
|
|
|
|
---
|
|
|
|
## FORMAT PER ENTRY
|
|
```
|
|
### LEARNING-NNN: Kort tittel
|
|
Dato: YYYY-MM-DD
|
|
Kontekst: Hva skjedde
|
|
Lærdom: Hva som er sant
|
|
Regel: Hva som alltid gjøres nå
|
|
Implementert i: [fil/script/gate]
|
|
```
|
|
|
|
---
|
|
|
|
### LEARNING-001: Branch-blindness koster $0.50+/feil
|
|
Dato: 2026-05-18
|
|
Kontekst: Phase A scratchpad sjekket kun `main`-branch i vauco-os. `autoflow-lag-1` var canonical med full operativ kode. Hele Phase A-analysen ble feil, og Phase B-planen ble bygget på feil premiss.
|
|
Lærdom: Default branch er ALDRI automatisk canonical. Alltid sjekk alle branches og finn den med mest aktive commits.
|
|
Regel: Boot-protokoll starter ALLTID med branch-discovery. Hvis 1+ branch er 10+ commits ahead av default: STOPP og spør Chris.
|
|
Implementert i: `docs/AGENTRLEBOOK.md` — BOOT-PROTOKOLL steg 1
|
|
|
|
---
|
|
|
|
### LEARNING-002: Handoff-MD er ferskvare — utdatert på 13 timer
|
|
Dato: 2026-05-18
|
|
Kontekst: VAUCO_BOOTSTRAP_HANDOFF_NEMOTRON.md ble utdatert samme dag den ble skrevet. MASTER_HANDOFF_v2 måtte lages for å reconcile motstridende info.
|
|
Lærdom: Statiske handoff-filer divergerer fort fra live state. SYSTEM_STATE_AGENT_BOOT.md (EXEC eier) må regenereres ved hver tråd-boot for å være autoritet på hva som er sant nå.
|
|
Regel: EXEC-tråden kjører `scripts/boot-state.sh` ved hver sesjon og skriver fersk SYSTEM_STATE_AGENT_BOOT.md.
|
|
Implementert i: TASK-FRICTION-002 — `scripts/boot-state.sh` (Day 2)
|
|
|
|
---
|
|
|
|
### LEARNING-003: 40% av Phase B var nyttig — resten død/avfeilet
|
|
Dato: 2026-05-18
|
|
Kontekst: Phase B-plan var bygget på feil premiss (tom remote repo), men inneholdt gode design-elementer: task manager, dev-orchestrate.sh, doc-consolidation layout.
|
|
Lærdom: Selv feil-premiss-planer kan inneholde nyttige sub-komponenter. Skill økten mellom premiss-validering og løsnings-design.
|
|
Regel: Før ny plan: verifiser alle premisser eksplisitt. Ground truth wins always. Innrøm direkte, oppdater eid fil, fortsett.
|
|
Implementert i: `docs/AGENTRLEBOOK.md` — KORREKSJONS-REGEL
|
|
|
|
---
|
|
|
|
### LEARNING-004: Pre-commit hook kan ikke skille regel-definisjon fra regelbrudd
|
|
Dato: 2026-05-18
|
|
Kontekst: `.githooks/pre-commit` bruker innholdsbasert regex-gate. Fanger `vertexai.generative_models` overalt — inkludert i NEVER-lister og kommentarer.
|
|
Lærdom: Semantisk korrekt bypass (`--no-verify` eller `git config --unset core.hooksPath`) er riktig for commits som inneholder regel-definisjoner, ikke regelbrudd.
|
|
Regel: Hook v2 må implementere Argument C: kun match uncommented lines i .py/.sh, og kun utenfor NEVER/blocked/forbid-kontekst i .md.
|
|
Implementert i: TASK-FRICTION-003 — hook v2 (Day 2)
|
|
|
|
---
|
|
|
|
### LEARNING-005: Verdivurdering før commit — tråden kan absorbere korreksjon raskt
|
|
Dato: 2026-05-18
|
|
Kontekst: Doc-konsolidering ble nødvendig (LEARNINGS.md, AGENTRLEBOOK.md). Ground-truth-vinner-alltid-prinsippet fungerte raskt i praksis.
|
|
Lærdom: Kjør verdivurdering ved slutten av hver økt: hva produserte vi, hva er nyttig vs dødt, hvilken læring overlever?
|
|
Regel: Før tråd-økt avsluttes: oppdater LEARNINGS.md (append), og friction → TASK-FRICTION-NNN i ROADMAP.
|
|
Implementert i: `docs/AGENTRLEBOOK.md` — FRICTION-REGLER
|
|
|
|
---
|
|
EOF — append videre under denne linjen
|
|
|
|
|
|
---
|
|
|
|
### LEARNING-006: gcloud-CLI deler quota med system-prosesser (32555940559)
|
|
Dato: 2026-05-18
|
|
Kontekst: gcloud CLI bruker shared project 32555940559 for cloudresourcemanager API. Loop-scripts trigget 2400 RPM cap. Årsak: boot-script eller watch-prosess listet prosjekter/billing i loop.
|
|
Lærdom: Quota-hit på shared gcloud-prosjekt er ikke-fatal, forsvinner etter 60s. Sjekk alltid ps aux for spam-prosesser før loop-operasjoner.
|
|
Regel: 1) Skriv Y ved quota-prompt → 2) vent 60s → 3) kjør preflight.sh på nytt. Ved 429: `ps aux | grep -E "(gcloud|gemini|watch)" | grep -v grep` → kill -9 <PID> ved looping prosess.
|
|
Implementert i: `scripts/preflight.sh` — kandidat for quota-check i v1.2 (TF-004)
|
|
|
|
---
|
|
|
|
### LEARNING-007: Bindestrek er ugyldig i bash-funksjonsnavn (POSIX strict)
|
|
Dato: 2026-05-25
|
|
Kontekst: Cloud Shell kjører `-bash` i POSIX strict mode. `opax-logg-slutt() {` kastet syntax error. Funksjonen var definert korrekt men navn med bindestrek er ikke tillatt i POSIX sh.
|
|
Lærdom: Funksjonsnavn i bash-scripts som skal kjøres i Cloud Shell MÅ bruke understrek, ikke bindestrek. Alias kan fortsatt bruke bindestrek og peke på understreks-funksjonen.
|
|
Regel: Alle funksjoner i `scripts/` bruker understrek (`opax_logg_slutt`). Aliaser for brukervennlighet kan ha bindestrek (`alias opax-logg-slutt='opax_logg_slutt'`).
|
|
Implementert i: `scripts/osvauco-opax-boot.sh` — fix pushet HEAD 1cea31d
|
|
|
|
---
|
|
|
|
### LEARNING-008: rclone med GDrive service account krever eksplisitt mappedeling
|
|
Dato: 2026-05-25
|
|
Kontekst: GitHub Actions nattlig backup feilet første kjøring. Årsak: service account (`vauco-gdrive-backup@...`) hadde ikke tilgang til GDrive-mappen selv om JSON-nøkkel og Secret var korrekt satt.
|
|
Lærdom: GDrive-mapper er ikke automatisk tilgjengelig for service accounts selv om de har riktig IAM-rolle. Mappen MÅ deles eksplisitt med service account-eposten (Editor-tilgang) i GDrive UI.
|
|
Regel: Ved oppsett av rclone/GDrive-backup: del ALLE målmapper med SA-epost manuelt i GDrive. Dokumenter i `docs/GDRIVE_SETUP.md`.
|
|
Implementert i: `docs/GDRIVE_SETUP.md` — steg 3
|
|
|
|
---
|
|
|
|
### LEARNING-009: .gdrive-mirror-state som SHA-anker forhindrer falske OK-varsler
|
|
Dato: 2026-05-25
|
|
Kontekst: Boot-dashboard viste alltid "fersk mirror" selv om GDrive ikke var oppdatert. Årsak: ingen persistert state å sammenligne mot.
|
|
Lærdom: Synkroniseringsstatus uten persistert anker er ubrukelig. `.gdrive-mirror-state`-filen (LAST_SYNC + LAST_SHA) gir boot-scriptet et faktisk sammenligningspunkt mellom sesjoner.
|
|
Regel: Ethvert sync-script skal skrive en state-fil med tidsstempel + commit-SHA. Boot leser denne og varsler ved avvik.
|
|
Implementert i: `scripts/sync-gdrive-mirror.sh` + `scripts/osvauco-opax-boot.sh`
|
|
|
|
---
|
|
|
|
### LEARNING-010: Cloud Build 2nd gen hadde foreldet glitch-repo-link
|
|
Dato: 2026-05-28
|
|
Kontekst: Cloud Build hadde to GitHub-kontoer koblet parallelt. Triggeren `osvauco-agent-main-trigger` pekte korrekt på `vauco-saas/OSVauco` (1st gen), men `osvauco-repo` under 2nd gen connection `osvauco-github-conn` pekte på `chrischristiansen-glitch/OSVauco` — en foreldet personlig konto.
|
|
Lærdom: CI/CD-triggere og repository-links er separate ressurser i Cloud Build. En trigger kan peke riktig mens en tilhørende repo-link er foreldet. Begge må verifiseres eksplisitt.
|
|
Regel: Ved GitHub-kontobytter: kjør alltid `gcloud builds repositories list --connection=<conn> --region=us-central1` og `gcloud builds triggers list` for å verifisere at BEGGE peker på riktig org. Slett foreldet repo-link umiddelbart.
|
|
Implementert i: Ryddet 2026-05-28 — `gcloud builds repositories delete osvauco-repo --connection=osvauco-github-conn --region=us-central1`. Bekreftet: "Listed 0 items."
|
|
|
|
---
|
|
|
|
### LEARNING-011: Cloud Build 2nd gen krever ny connection ved org-bytte
|
|
Dato: 2026-05-28
|
|
Kontekst: Forsøkte å koble `vauco-saas/OSVauco` til eksisterende `osvauco-github-conn` (installasjon ID 135008388, tilhørende `chrischristiansen-glitch`). Fikk feil: "repository does not exist or is not accessible". Årsak: GitHub App-installasjonen var bundet til feil konto.
|
|
Lærdom: En Cloud Build connection er bundet til én GitHub-konto/org via GitHub App installation ID. Du kan ikke koble repos fra en annen org uten å opprette ny connection med riktig installasjon.
|
|
Regel: Ved org-bytte (f.eks. glitch → vauco-saas): opprett alltid ny connection med `gcloud builds connections create github <navn> --region=us-central1`, autoriser i nettleser mot riktig org, så legg til repo.
|
|
Implementert i: Fullført 2026-05-28:
|
|
- Ny connection: `osvauco-vauco-saas-conn` (us-central1)
|
|
- Autorisert mot `vauco-saas`-org i GitHub
|
|
- Repo-link: `osvauco-repo` → `https://github.com/vauco-saas/OSVauco.git` ✅
|
|
- Gammel connection `osvauco-github-conn` (glitch) kan slettes når trigger er migrert
|
|
|
|
---
|
|
|
|
### LEARNING-012: VertexAiRagRetrieval og FunctionTool kan ikke kombineres i samme agent
|
|
Dato: 2026-06-10
|
|
Kontekst: CI6 — `root_agent` hadde både RAG og MCP FunctionTools. AFC (Automatic Function Calling) ble deaktivert fordi `VertexAiRagRetrieval` ikke er en Python callable. Agenten kalte aldri MCP-verktøyene.
|
|
Lærdom: ADK slår av AFC stille hvis én tool i lista ikke er AFC-kompatibel. Ingen feilmelding — agenten bare ignorerer verktøyene.
|
|
Regel: RAG isoleres ALLTID i en dedikert sub-agent. `root_agent` får kun FunctionTools. Miks er forbudt.
|
|
Implementert i: `agents/core-logic/agent.py` — RAG fjernet fra root_agent (commit 3bb95c8). TODO: RAG sub-agent.
|
|
|
|
---
|
|
|
|
### LEARNING-013: Cloud Run krever identity token, ikke access token
|
|
Dato: 2026-06-10
|
|
Kontekst: CI6 — `_opax_headers()` brukte `google.auth.default()` som gir OAuth2 access token. Cloud Run (no-allow-unauthenticated) krever identity token med riktig `aud`-claim. Begge gir 401 men av ulik grunn.
|
|
Lærdom: `google.auth.default()` ≠ identity token. For Cloud Run-til-Cloud Run kall: bruk alltid GCE metadata server med `?audience=<service-url>`.
|
|
Regel: All server-til-server autentisering mot Cloud Run bruker:
|
|
`http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=<URL>`
|
|
Implementert i: `agents/core-logic/mcp_tools.py` — commit 8013bd8
|
|
|
|
---
|
|
|
|
### LEARNING-014: Secrets må mountes eksplisitt på hver Cloud Run-tjeneste
|
|
Dato: 2026-06-10
|
|
Kontekst: CI6 — `mcp-server-key` fantes i Secret Manager men var ikke mountet på `osvauco-agent`. Agenten sendte tom `X-MCP-Key`-header. `opax-mcp` avviste alle kall med 401.
|
|
Lærdom: Secret Manager-secrets er ikke automatisk tilgjengelig for Cloud Run-tjenester. Hver tjeneste må ha eksplisitt `--update-secrets` i deploy-kommandoen.
|
|
Regel: `cloudbuild.yaml` bruker nå `--update-secrets` for ALLE required secrets inkl. `MCP_SECRET`. `.env.example` dokumenterer alle secrets.
|
|
Implementert i: `cloudbuild.yaml` (CI7) + `agents/core-logic/.env.example` (CI6)
|
|
|
|
---
|
|
|
|
### LEARNING-015: Ikke anta issue-status fra MASTERPLAN — sjekk faktisk state
|
|
Dato: 2026-06-10
|
|
Kontekst: MASTERPLAN #4 viste C1b som "IN PROGRESS" (DNS-endring). DNS hadde vært i orden i 1-2 uker. Agent antok blokkering uten å verifisere.
|
|
Lærdom: Dokumenter divergerer fra virkelighet. Statuser i MASTERPLAN/issues er ikke self-updating.
|
|
Regel: Spør alltid Chris om usikker status fremfor å anta. Grunnregel: ground truth > dokument.
|
|
Implementert i: `docs/MASTERPLAN.md` — C1b markeres done
|
|
|
|
---
|
|
|
|
### LEARNING-016: opax.vauco.no bruker osvauco-agent-iap-backend, ikke vauco-os-backend
|
|
Dato: 2026-06-17
|
|
Kontekst: IAP-binding ble forsøkt lagt til vauco-os-backend fordi vauco-os-urlmap bruker
|
|
den som defaultService. Men opax.vauco.no DNS A-record peker til 34.98.77.173 som er
|
|
osvauco-agent-forwarding-rule, ikke vauco-os (34.144.224.45).
|
|
Fasit: opax.vauco.no -> 34.98.77.173 -> osvauco-agent-url-map -> osvauco-agent-iap-backend.
|
|
Den opprinnelige IAP-bindingen (steg 3) var korrekt.
|
|
Lærdom: Backend-navn i GCP matcher ikke nødvendigvis subdomene-navn.
|
|
Regel: Ved IAP-binding: sjekk DNS A-record -> forwarding rule IP -> url-map -> backend.
|
|
Ikke anta fra URL-map-navn. Bruk:
|
|
1. nslookup <domene> # finn IP
|
|
2. gcloud compute forwarding-rules list --global # match IP -> url-map
|
|
3. gcloud compute url-maps describe <url-map> --global | grep defaultService
|
|
Implementert i: docs/DNS-OG-INFRASTRUKTUR.md oppdatert med korrekt routing-kart
|
|
|
|
---
|
|
|
|
### LEARNING-017: På GCE VM skal IAP alltid bruke metadata-server token, ikke ADC fra brukerlogin
|
|
Dato: 2026-06-28
|
|
Kontekst: Test mot `https://opax.vauco.no/health` feilet med `Invalid IAP credentials: Unable to parse JWT` etter at brukerbasert auth/ADC hadde utløpt i en SSH-økt på VM. Dette skapte støy fordi VM-en allerede har service account og stabil auth-kanal tilgjengelig.
|
|
Lærdom: På GCE VM er `gcloud auth application-default login` midlertidig og brukerbundet. For IAP-kall fra VM skal identity token alltid hentes fra metadata-serveren med riktig audience, siden dette bruker VM-ens service account og ikke utløper på samme måte i arbeidsflyten.
|
|
Regel: Alle IAP-kall fra `osvauco-dev-vm` bruker:
|
|
`TOKEN=$(curl -sf "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=357036551735-kq8nt7ld38hfqlcfb3n52ef7tala4meo.apps.googleusercontent.com&format=full" -H "Metadata-Flavor: Google")`
|
|
etterfulgt av:
|
|
`curl -s https://opax.vauco.no/health -H "Authorization: Bearer $TOKEN"`
|
|
Ikke bruk ADC/user-login som primær metode for IAP fra VM.
|
|
Implementert i: `docs/LEARNINGS.md` (append-only), neste steg `scripts/boot.sh` / testprosedyrer
|
|
|
|
### LEARNING-018: Agent-metodikk for Infrastruktur-endringer
|
|
Dato: 2026-07-07
|
|
Kontekst: En serie feilkonfigurasjoner i lastbalansering for Gitea ble identifisert og løst ved å følge en strukturert, iterativ prosess.
|
|
Lærdom: For å sikre trygge og forutsigbare endringer, må en fast metodikk følges.
|
|
Regel: Følgende metode skal brukes for infrastruktur-endringer:
|
|
1. **Diagnose:** Start alltid med read-only-kommandoer (`describe`, `list`, `get`) for å forstå nå-situasjonen. Ikke anta at dokumentasjon er 100% korrekt.
|
|
2. **Målarkitektur:** Definer og bli enige om en klar målarkitektur før løsninger foreslås.
|
|
3. **Planlegg & Dokumenter:** Skriv planen inn i relevant dokument (`HANDOFF.md`, etc.) som en "ikke utført" TODO-liste. Identifiser og dokumenter alle blockere.
|
|
4. **Små Steg:** Utfør planen i de minste, logiske stegene.
|
|
5. **Verifiser:** Verifiser resultatet med en test (`curl`, `gsutil ls`, etc.) umiddelbart etter *hver* endring.
|
|
6. **Oppdater Sannhet:** Oppdater dokumentasjonen med resultatet, slik at neste økt starter fra en korrekt tilstand.
|
|
Implementert i: Hele Gitea LB-fiksen (juli 2026). Nå formalisert her for fremtidig bruk.
|