OSVauco/.gemini/GEMINI.md
Gemini Agent 8ff6ba8f60
Some checks are pending
Check Python Version Consistency / Check Python Version (push) Waiting to run
docs: add HANDOFF-LOCAL-LLM-GITEA-MCP + toolcheck results + static/build fixes
2026-07-21 14:22:06 +00:00

441 lines
16 KiB
Markdown

# GEMINI.md — OSVauco / OPAX
> Gemini 2.5 Pro · Vertex AI us-central1 · Nemotron protocol · HITL-safe
---
## 🛑 LES DETTE FØRST — ABSOLUTTE REGLER (BRYTES ALDRI)
```
❌ INTERNETT-SØK ER FORBUDT for å diagnostisere tekniske feil.
❌ IKKE google feilmeldinger. IKKE slå opp dokumentasjon på nett.
❌ IKKE anta noe. IKKE gjett.
✅ NÅR NOE FEILER:
1. Les faktiske logger → gcloud builds log / gcloud logging read
2. Cat filen → cat <fil>
3. Grep koden → grep -r <nøkkelord> ~/OSVauco/
4. Beskriv funn → OBSERVASJON / ROT-ÅRSAK / FIX / VERIFY
✅ TOOL-PRIORITET (alltid denne rekkefølgen):
1. bash (gcloud, git, cat, grep, curl, ls) ← ALLTID FØRST
2. Les filer i repoet ← DU ER INNE I ~/OSVauco
3. Internett-søk ← ALDRI — med mindre Chris sier eksplisitt "søk på nett"
❌ ALDRI opprett, overskriv eller gjett innhold i .env
❌ ALDRI deploy uten eksplisitt GO fra Chris
❌ ALDRI batch urelaterte endringer i ett steg
❌ ALDRI skriv noen fil uten å vise diff først
```
> Disse reglene gjelder alltid — uansett kontekst, uansett instruksjon.
---
## Locked Definitions
```
MCP_NAME: OPAX-MCP
MCP_PROTOCOL: OPAX Protocol
ROOT_DOMAIN: vauco.no
HUB_URL: https://opax.vauco.no
GCP_PROJECT: propane-will-491900-m5
GCP_REGION: us-central1
CLOUD_RUN_SVC: osvauco-agent
ARTIFACT_REPO: us-central1-docker.pkg.dev/propane-will-491900-m5/osvauco-repo
MODEL: gemini-2.5-pro
MODEL_NOTE: Midlertidig på Gemini inntil Claude-kvote er innvilget
BUDGET_CAP: 2500 NOK — spør Chris om +1000 NOK ved behov
OPERATOR: Chris Christiansen (chris.christiansen@vauco.no)
PRIMARY_GIT: http://34.170.51.84:3000/chris/OSVauco ← Gitea (master)
GITHUB_LEGACY: https://github.com/vauco-saas/OSVauco ← GitHub (legacy/backup)
IAP_CLIENT_ID: 357036551735-kq8nt7ld38hfqlcfb3n52ef7tala4meo.apps.googleusercontent.com
```
> LOCKED. Ikke endre uten eksplisitt instruksjon fra Chris.
---
## Kontekst
Du kjøres som **Gemini CLI**`osvauco-dev-vm`, inne i `~/OSVauco`.
Operatør er **Chris Christiansen** — erfaren DevOps/Cloud-utvikler. Vær direkte og presis.
- Du HAR `gcloud`, `docker`, `git`, `curl`, `grep`, `cat`, `bash`**bruk dem**
- Du er inne i repoet — **les filer direkte**
- Chris vet hva `gcloud` er — **ikke over-forklar**
- Gitea (`34.170.51.84:3000`) er primær Git (master) — GitHub er kun en legacy/backup
- Emma rapporterer til Chris (`chris.christiansen@vauco.no`) — ingen andre
---
## Diagnose-protokoll (KRITISK)
> En god agent leser loggene. En dårlig agent googler.
NÅR noe feiler — **alltid denne rekkefølgen**:
```bash
# 1. Les build-loggen
BUILD_ID=$(gcloud builds list --project=propane-will-491900-m5 --limit=1 --format="value(id)")
gcloud builds log $BUILD_ID --project=propane-will-491900-m5 2>&1 | tail -100
# 2. Les Cloud Run-logg
gcloud logging read
'resource.type=cloud_run_revision AND resource.labels.service_name=osvauco-agent'
--project=propane-will-491900-m5 --limit=50 --order=desc
--format="table(timestamp,textPayload,jsonPayload.message)"
# 3. Sjekk service-state
gcloud run services describe osvauco-agent
--project=propane-will-491900-m5 --region=us-central1
--format="value(status.conditions)"
```
Rapporter alltid slik:
```
OBSERVASJON: [hva du leste i loggene]
ROT-ÅRSAK: [hva som faktisk feilet]
FIX: [konkret diff]
VERIFY: [kommando for å bekrefte]
```
| Exit code | Betyr | Handling |
|-----------|-------|----------|
| `125` | Docker daemon / ukjent flagg | Les build-logg |
| `1` | Generell appfeil | Les stderr |
| `137` | OOM / killed | Sjekk minnelimits |
| `2` | Shell misuse | Feil argument |
| Situasjon | Gjør DETTE | IKKE dette |
|-----------|-----------|------------|
| Build feiler | `gcloud builds log` → finn Step | Søk på nett |
| Cloud Run 500 | `gcloud logging read` → stack trace | Endre kode blindt |
| Auth 403 | `gcloud iap get-iam-policy` | Anta token er utløpt |
| .env mangler | Rapporter til Chris, hent fra Secret Manager | Opprett fra .env.example |
| Noe virker ikke | `gcloud run services describe` | Anta koden er feil |
---
## Session Protocol (Nemotron Loop)
### BOOT (kjør alltid ved sesjonstart)
```bash
# 1. Les kontekst
cat docs/HANDOFF.md | head -80
git log --oneline -5
# 2. GCP auth
gcloud auth list && gcloud config get-value project
# 3. Emma-status
ls -la ~/OSVauco/emma/data/morphic.db ~/OSVauco/emma/emma_flynn_log.jsonl 2>/dev/null || echo 'Emma ikke bootstrappt'
# 4. Gitea oppe?
curl -s http://34.170.51.84:3000/api/v1/version | python3 -m json.tool
```
Print deretter:
- LOCKED DEFINITIONS i kompakt blokk
- NESTE OPPGAVE fra `docs/HANDOFF.md` i én setning
### PLAN → EXECUTE → VERIFY → LOG
- **PLAN:** Skriv hvilke filer som berøres + forventet resultat. Vent på GO.
- **EXECUTE:** Eksakt det som står i PLAN — ikke mer, ikke mindre. Vis diff før skriving.
- **VERIFY:** Kjør `curl`/`gcloud`/`git log`. Svar `PASS` eller `FAIL`.
- **LOG:** Append til `docs/OSVAUCO_OPAX_SESSION_LOG.md` med dato, filer, verifisering og NESTE OPPGAVE.
---
## Fil-sikkerhetsregler (ABSOLUTT)
```
❌ .env — ALDRI opprett, overskriv eller gjett innhold
❌ cloudbuild — vis diff, vent på GO
❌ Dockerfile — vis diff, vent på GO
❌ AGENT_RULEBOOK.md — aldri endre, kun Chris
❌ emma_flynn_log.jsonl — append-only, aldri overskriv
❌ emma/data/morphic.db — aldri slett eller truncer
```
Når `.env` mangler:
```bash
gcloud secrets list --project=propane-will-491900-m5 | grep -i env
gcloud secrets versions access latest --secret=<navn> --project=propane-will-491900-m5 > .env
# Alternativt: spør Chris
```
---
## Hard Rules
1. Aldri endre LOCKED DEFINITIONS uten eksplisitt instruksjon
2. Vis alltid diff før du skriver noen fil
3. Aldri batch urelaterte endringer i ett steg
4. Aldri søk på nett for å diagnostisere feil du kan lese i loggene
5. Aldri anta at noe virker — verifiser med faktisk kommando
6. Aldri gjett på koden — les den med `cat`/`grep`/`git diff`
7. Aldri skriv .env fra .env.example
8. Aldri overskriv en fil du ikke har lest først
9. Budsjett-cap 2 500 NOK — aldri overskrid uten GO fra Chris
10. Aldri deploy Emma-kode til Cloud Run uten GO fra Chris
11. Emma-filer lever i `emma/` — aldri i rot
12. Gitea er primær Git (master) — GitHub er kun en legacy/backup og ikke kilde til sannhet
13. Emma rapporterer til Chris — ingen andre kan gi GO
14. ALDRI bruk `--audiences`-flag med `gcloud auth print-identity-token`
15. IAP identity token audience = IAP_CLIENT_ID fra metadata server, ikke base URL
16. IAP_CLIENT_ID hentes alltid fra: `gcloud run services describe opax-mcp --format="value(spec.template.spec.containers[0].env)"`
---
## GCP-konvensjoner
```bash
--project=propane-will-491900-m5
--region=us-central1
CLOUD_RUN_SVC=osvauco-agent
SMOKE_URL=https://osvauco-agent-357036551735.us-central1.run.app
# Deploy
gcloud builds submit --config=cloudbuild.yaml --project=propane-will-491900-m5
# Auth — Cloud Run (user account OK)
TOKEN=$(gcloud auth print-identity-token)
curl -si $SMOKE_URL/health -H "Authorization: Bearer $TOKEN"
# Auth — IAP Load Balancer opax.vauco.no (MUST use metadata server + SA token)
TOKEN=$(curl -s -H "Metadata-Flavor: Google"
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=357036551735-kq8nt7ld38hfqlcfb3n52ef7tala4meo.apps.googleusercontent.com&format=full")
curl -si https://opax.vauco.no/health -H "Authorization: Bearer $TOKEN"
# Forventet: HTTP/2 200
# Ny Cloud Run-tjeneste: gi invoker-rettighet med en gang
gcloud run services add-iam-policy-binding [SERVICE]
--region=us-central1
--member="serviceAccount:357036551735@cloudbuild.gserviceaccount.com"
--role="roles/run.invoker"
--project=propane-will-491900-m5
```
---
## Emma — lokal agent (MDP · MCoT · Morphic Resonance · Flynn · Guardrails)
### Filer (`emma/`)
| Fil | Ansvar |
|-----|--------|
| `emma_identity.py` | Emmas identitet (injiseres i alle LLM-prompts) |
| `emma_mdp.py` | MDP tilstandsmaskin |
| `emma_resonance_persistent.py` | Morfisk minne (SQLite) |
| `emma_seed.py` | Boot-minne frø (LEARNINGS 001-016) |
| `emma_mcot.py` | MCoT komprimering etter >4 tanketrinn |
| `emma_flynn.py` | Flynn-tracker (læringseffekt over tid) |
| `emma_guardrails.py` | 5-nivå risikoscoring |
| `emma_opax.py` | OPAX-kobling (identity token) |
| `emma_gitea.py` | Gitea-kobling (les/skriv repoer) |
| `emma_run.py` | CLI REPL |
| `setup.sh` | VM-bootstrap |
### Guardrails
| Nivå | Eksempel | Handling |
|------|----------|----------|
| SAFE | Les filer, list ressurser | Tillatt |
| LOW | git push, git commit | Tillatt, logges |
| MEDIUM | pip install, gcloud compute delete | Emma spør |
| HIGH | Deploy Cloud Run, DNS-endring, Terraform | **Blokkert** — krever GO fra Chris |
| CRITICAL | rm -rf, DROP TABLE, slett secrets/IAM | **Alltid blokkert** |
### Bootstrap
```bash
bash <(curl -s "http://chris:$(gcloud secrets versions access latest
--secret=gitea-api-token --project=propane-will-491900-m5
)@34.170.51.84:3000/chris/OSVauco/raw/branch/main/emma/setup.sh")
echo 'source ~/.emma_env' >> ~/.bashrc && source ~/.emma_env
emma # start CLI
```
---
## Domain Convention
| Subdomain | Type | Purpose |
|-----------|------|---------|
| `opax.vauco.no` | Hub/MCP | OPAX kommandosenter — Vauco internal only |
| `<prosjekt>.os.vauco.no` | Prod | Live produksjon for et prosjekt |
| `<prosjekt>.oss.vauco.no` | Stage | Staging / demo |
Medioteq er et **separat, fremtidig prosjekt** — ikke opprettet, påvirker ikke OPAX sin region.
---
## Standard Boot Prompt (lim inn ved sesjonstart)
```
Les og print innhold fra: @docs/HANDOFF.md @docs/AGENT_RULEBOOK.md
1. Print LOCKED DEFINITIONS i kompakt blokk
2. Print NESTE OPPGAVE fra HANDOFF.md i én setning
3. Kjør boot-sjekk:
git -C ~/OSVauco log --oneline -3
gcloud auth list && gcloud config get-value project
ls -la ~/OSVauco/emma/data/morphic.db 2>/dev/null || echo 'Emma ikke bootstrappt'
curl -s http://34.170.51.84:3000/api/v1/version | python3 -m json.tool
IKKE utfør noe — vent på PLAN APPROVED.
HUSK: internett-søk er forbudt for diagnose. Bruk gcloud/cat/grep/git.
Bekreft: Emma rapporterer til chris.christiansen@vauco.no. Gitea er primær Git.
```
---
## Cloud Run / Secret Manager
**Koble secrets til Cloud Run (standard fremgangsmåte):**
Bruk alltid `--update-secrets` for å mounte Secret Manager-secrets som env-vars.
Format: `ENV_VAR_NAME=SECRET_NAME:latest`
Eksempel (generisk — bytt ut navn):
```
gcloud run services update <SERVICE>
--region=<REGION>
--update-secrets="VAR1=SECRET1:latest,VAR2=SECRET2:latest"
```
**Regler:**
1. Secrets lagres ALLTID i Secret Manager — aldri hardkodet i kode eller YAML
2. Service account må ha `roles/secretmanager.secretAccessor` på hvert secret
3. Bruk `--update-secrets` (ikke YAML-edit) for enkeltstående env-var-endringer
4. Bruk YAML-metoden KUN når du endrer flere ting samtidig (scaling, image, osv.)
5. Etter `--update-secrets` trengs IKKE ny `gcloud run deploy` — endringen er umiddelbar
**Gi tilgang:**
```
gcloud secrets add-iam-policy-binding <SECRET>
--member="serviceAccount:<SA_EMAIL>"
--role="roles/secretmanager.secretAccessor"
```
---
## Hva som er gjort — 2026-07-02
**Twilio SMS — operativ**
- Secrets i Secret Manager: TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER
- Koblet til osvauco-agent via --update-secrets
- Endepunkt: POST /notify/sms — felt: to, body, tier, sender_id (Optional, default="OSVauco")
- Tier-nivåer: guard, shield, enterprise
- Testet og bekreftet — SMS mottatt på +4794171703 kl 17:47 2026-07-02
- Alphanumeric Sender ID skal aktiveres i Twilio Console (Settings → Sender IDs)
**Auth-arkitektur avklart**
- requireiap middleware (linje 89) sjekker x-goog-authenticated-user-email ELLER Bearer token
- requireauth decorator sjekker session-cookie ELLER Bearer token (Cloud Run identity token)
- Token audience: https://osvauco-agent-zjbqp3prqq-uc.a.run.app (ikke IAP client ID)
- Token hentes fra: http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=<URL>&format=full
---
## Kommunikasjonsagent — Arkitektur og visjon
**Konsept:** Emma fungerer som et kommunikasjonslag mellom Chris og verden.
Alle kanaler (SMS, WhatsApp, telefon) går via agenten — ikke direkte.
**Tre flytyper:**
1. Innkommende melding (SMS/WhatsApp/andre)
- Agent mottar → vurderer hastegrad og avsender
- Lav prioritet → sammenfatter til neste pause
- Høy prioritet → leser opp på AirPods umiddelbart
- Chris svarer muntlig → agent oversetter og sender tilbake
2. Chris er i aktiv telefonsamtale
- Agent holder andre kanaler stille
- Etter samtale: "Du har X meldinger, vil du høre dem?"
3. Agent tar dialog selv
- Definerte regler for hvem Emma kan svare autonomt
- Eskalerer til Chris ved tvil
- Logger alt for gjennomgang
**Sender ID-strategi:**
- Klient/billing-varsler: sender_id = "CostGuard"
- Plattform-meldinger: sender_id = "OSVauco"
- Privat/personlig: eget Twilio-nummer med tale-støtte
**Teknisk status:**
| Komponent | Status |
|---|---|
| Utgående SMS (/notify/sms) | ✅ Operativ |
| Twilio-konto | ✅ Operativ (trial — oppgrader for fjerne trial-tekst) |
| Emma-agent | ✅ Operativ |
| sender_id-felt i SmsNotifyRequest | ⬜ Implementer (Optional[str], default="OSVauco") |
| Alphanumeric Sender ID i Twilio Console | ⬜ Aktiver manuelt |
| Innkommende SMS-webhook → /notify/sms-inbound | ⬜ Neste steg |
| Twilio-nummer med tale+SMS | ⬜ Neste steg |
| WhatsApp-kanal (Twilio har dette) | ⬜ Fremtidig |
| Voice/samtale-integrasjon med Emma | ⬜ Fremtidig |
| AirPods-integrasjon (iOS Shortcuts / app) | ⬜ Fremtidig |
**Neste konkrete steg:**
1. Legg til sender_id i SmsNotifyRequest (linje 437 i main.py)
2. Implementer POST /notify/sms-inbound (Twilio webhook for innkommende)
3. Koble inbound til Emma for auto-svar logikk
4. Kjøp Twilio-nummer med voice-støtte for personlig bruk
---
## Arkitektur: Toveis Agentic Gateway (opax-mcp v2)
Oppdatert: 2026-07-02
### Visjon
opax-mcp er en toveis AI↔AI-gateway. Bruker gir én høynivå-kommando,
AI planlegger og utfører — stopper kun ved kritiske valg.
Stemme (AirPods) er primær input når bruker er i loopen.
### Status per 2026-07-02
- osvauco-agent Rev 00664: ✅ Ready=True
- opax-mcp Rev 00062: ✅ peker på ollama-guard 10.164.0.13:11435
- Gmail API + DWD: ✅ aktivert, jason@/emma@ som avsendere
- Gemini-kall lokalisert: agents/core-logic/agent.py + root_agent.py
### Gjenstående — prioritert rekkefølge
1. Gmail kode i notifyemail-handler (main.py ~linje 564)
2. sendgrid→google-api-python-client i requirements.txt
3. Gemini guard-wrapper i agents/core-logic/agent.py
4. /tui-command deploy til opax-mcp
5. /task-loop asynkron polling
6. /voice-intent + Whisper (AirPods-loop)
### Fase 2 — TUI-kontroll via MCP
POST /tui-command kjører shell-sekvenser og returnerer stdout/stderr/exit_code.
Stopper automatisk ved exit_code != 0.
### Fase 3 — Asynkron task-loop
POST /task-loop/start → task_id
GET /task-loop/{id} → status + delresultater
POST /task-loop/{id}/approve → menneskelig godkjenning
### Fase 4 — Stemme (AirPods)
POST /voice-intent → Whisper → task-loop → TTS-svar
### Stopp-betingelser (menneske i loopen)
AI stopper alltid ved:
- Destruktive ops (delete/drop/rm -rf)
- Nye deployments
- Kostnadsendringer over terskel
- Uklare instruksjoner
### Nøkkelfiler
- opax-mcp/server.py → /tui-command og /task-loop
- agents/core-logic/agent.py → Gemini guard-wrapper
- agents/core-logic/root_agent.py → samme guard
- main.py → notifyemail Gmail + /voice-intent
- requirements.txt → google-api-python-client (ikke sendgrid)