feat(gdrive-mirror): GDrive/GitHub paritet, backup, PROMPT_COMMAND logging (#1)

- GDRIVE_MIRROR_BOOT.md med staleness-varsel (12t terskel) og connector-prioritet
- sync-gdrive-mirror.sh: auto-tidsstempel, prosjektindeks, .gdrive-mirror-state
- osvauco-opax-boot.sh: alias auto-inject ~/.bashrc, GitHub vs lokal HEAD, PROMPT_COMMAND terminal-logging
- opax-logg-slutt.sh standalone
- .github/workflows/backup-gdrive-nightly.yml: nattlig git bundle + nøkkelfiler til GDrive
- docs/GDRIVE_SETUP.md: ett-gangs oppsett-guide for rclone + IAM
- docs/TODO.md: IAM/secrets-oppsett + gemini TUI-logging som neste oppgaver
This commit is contained in:
chrischristiansen-glitch 2026-05-25 11:39:28 +02:00 committed by GitHub
parent 25e36de810
commit 5728024b21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 706 additions and 33 deletions

View File

@ -0,0 +1,91 @@
name: Nightly GDrive Backup
# Kjører kl 03:00 UTC (05:00 CEST) hver natt + ved push til main
on:
schedule:
- cron: '0 3 * * *'
push:
branches:
- main
workflow_dispatch: # manuell trigger fra GitHub UI
jobs:
backup:
name: Backup OSVauco → Google Drive
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0 # full historikk for git bundle
# ── 1. Installer rclone ───────────────────────────────────────────────
- name: Install rclone
run: |
curl https://rclone.org/install.sh | sudo bash
rclone version
# ── 2. Konfigurer rclone med GDrive service account ───────────────────
# Forutsetter at RCLONE_GDRIVE_SA_JSON er lagt inn som GitHub Secret
# og at GDRIVE_BACKUP_FOLDER_ID peker på riktig GDrive-mappe
- name: Configure rclone
env:
RCLONE_GDRIVE_SA_JSON: ${{ secrets.RCLONE_GDRIVE_SA_JSON }}
GDRIVE_FOLDER_ID: ${{ secrets.GDRIVE_BACKUP_FOLDER_ID }}
run: |
mkdir -p ~/.config/rclone
cat > ~/.config/rclone/rclone.conf << EOF
[gdrive]
type = drive
scope = drive
service_account_credentials = ${RCLONE_GDRIVE_SA_JSON}
root_folder_id = ${GDRIVE_FOLDER_ID}
EOF
# ── 3. Nøkkelfiler (MD-indeks) → GDrive/vauco-mirror/ ─────────────────
- name: Sync key docs to GDrive mirror folder
run: |
rclone copy docs/AGENT_RULEBOOK.md gdrive:vauco-mirror/
rclone copy docs/GDRIVE_MIRROR_BOOT.md gdrive:vauco-mirror/
rclone copy docs/LEARNINGS.md gdrive:vauco-mirror/
rclone copy docs/VAUCO_OS_ROADMAP.md gdrive:vauco-mirror/
rclone copy docs/TODO.md gdrive:vauco-mirror/
rclone copy MASTERPLAN.md gdrive:vauco-mirror/
rclone copy protocols/sessions/index.md gdrive:vauco-mirror/sessions/
echo "[backup] Nøkkelfiler synkronisert → GDrive/vauco-mirror/"
# ── 4. Full repo-backup som git bundle → GDrive/vauco-backup/ ─────────
- name: Create git bundle
run: |
TIMESTAMP=$(date '+%Y-%m-%dT%H%M')
BUNDLE_NAME="OSVauco-backup-${TIMESTAMP}.bundle"
git bundle create "/tmp/${BUNDLE_NAME}" --all
echo "BUNDLE_NAME=${BUNDLE_NAME}" >> $GITHUB_ENV
echo "[backup] Bundle opprettet: ${BUNDLE_NAME}"
- name: Upload bundle to GDrive
run: |
rclone copy "/tmp/${{ env.BUNDLE_NAME }}" gdrive:vauco-backup/
echo "[backup] Bundle lastet opp → GDrive/vauco-backup/${{ env.BUNDLE_NAME }}"
# ── 5. Rydd gamle bundles (behold siste 7) ────────────────────────────
- name: Prune old bundles (keep last 7)
run: |
rclone ls gdrive:vauco-backup/ \
| sort -k2 \
| head -n -7 \
| awk '{print $2}' \
| xargs -I{} rclone deletefile gdrive:vauco-backup/{} || true
echo "[backup] Gamle bundles ryddet (behold 7 siste)"
# ── 6. Sammendrag ─────────────────────────────────────────────────────
- name: Summary
run: |
echo "=== BACKUP FERDIG ==="
echo "Tidspunkt : $(date '+%Y-%m-%dT%H:%M %Z')"
echo "Bundle : ${{ env.BUNDLE_NAME }}"
echo "Mirror : GDrive/vauco-mirror/ (nøkkelfiler)"
echo "Backup : GDrive/vauco-backup/ (git bundle)"
rclone ls gdrive:vauco-backup/ | sort -k2 | tail -7

191
docs/GDRIVE_MIRROR_BOOT.md Normal file
View File

@ -0,0 +1,191 @@
# VAUCO OS — GDRIVE MIRROR BOOT
> **CONNECTOR-PRIORITET:**
> ```
> GITHUB > GOOGLE DRIVE
> ```
> GitHub (`OSVauco/main/docs/AGENT_RULEBOOK.md`) er **alltid** ground truth.
> Denne filen er en leseliste for agenter/tråder uten GitHub-connector (f.eks. Gemini GDrive-modus).
> Ved enhver konflikt: stol på GitHub. Oppdater denne filen etterpå.
---
## ⚠️ STALENESS-VARSEL — LES DETTE FØRST
```
╔══════════════════════════════════════════════════════════════╗
║ SIST SYNKRONISERT FRA GITHUB: 2026-05-25T11:18 CEST ║
║ Kilde: OSVauco/main/docs/AGENT_RULEBOOK.md (v1.2) ║
║ Synkronisert av: OPS-Computer-Hub ║
╠══════════════════════════════════════════════════════════════╣
║ ⚠️ TERSKEL: 12 TIMER (aktiv dev-runde) ║
║ HVIS MER ENN 12T HAR GÅTT SIDEN OVENSTÅENDE TIDSPUNKT: ║
║ → STOPP — filen er sannsynligvis utdatert. ║
║ → Verifiser mot GitHub FØR du handler på instrukser. ║
╠══════════════════════════════════════════════════════════════╣
║ VERIFISER HER: ║
║ https://github.com/chrischristiansen-glitch/OSVauco/ ║
║ blob/main/docs/AGENT_RULEBOOK.md ║
╠══════════════════════════════════════════════════════════════╣
║ OPPDATER DENNE FILEN: ║
║ 1. Åpne lenken over ║
║ 2. Sammenlign «Sist oppdatert»-dato i AGENT_RULEBOOK.md ║
║ 3. Hvis nyere: last ned og erstatt denne filen i GDrive ║
╚══════════════════════════════════════════════════════════════╝
```
> **Tommelfingerregel (dev-runde):** Filen er fersk i **12 timer**. Etter det — verifiser alltid.
---
## CONNECTOR-GUIDE
| Tråd/Verktøy | Connector tilgjengelig | Bruk |
|---|---|---|
| Perplexity Computer (OPS) | GitHub MCP ✅ | Les direkte fra `AGENT_RULEBOOK.md` på GitHub |
| Gemini CLI / Workstation | GDrive ✅ / GitHub ❌ | Les denne filen — verifiser staleness-varsel øverst |
| Claude (PLAN) | Varierer | Foretrekk GitHub hvis tilgjengelig, ellers GDrive |
| Nemotron / AUDIT | Varierer | Foretrekk GitHub hvis tilgjengelig, ellers GDrive |
**Når du bruker GDrive og det har gått >12 timer siden SIST SYNKRONISERT:**
- STOPP
- Følg lenken i staleness-varselet over
- Bekreft eller oppdater før du fortsetter
---
## INNHOLD — KOPI AV AGENT_RULEBOOK.md v1.2 (2026-05-21)
> Kilde: https://github.com/chrischristiansen-glitch/OSVauco/blob/main/docs/AGENT_RULEBOOK.md
---
### LOCK LIST — ALDRI ENDRE
| Parameter | Verdi |
|---|---|
| GCP Account | chris.christiansen@vauco.no |
| Forbudte kontoer | tinius.vauger, ccv, jason.vauger |
| GCP Project | propane-will-491900-m5 (Jason-v1) |
| Billing | 0171F6-057E6B-A260BA |
| Org | vauco.no / 155051211891 |
| Region | us-central1 — ALDRI us-west1 |
| SDK | `from google import genai` — ALDRI `vertexai.generative_models` |
| Agent-rammeverk | Google ADK (tillatt) — andre krever `ADK_GODKJENT` fra Chris |
| GitHub user | chrischristiansen-glitch |
| Canonical repo | OSVauco |
| Canonical branch | main |
| MCP_NAME | OPAX-MCP |
| MCP_PROTOCOL | OPAX Protocol |
| MCP_SERVICE | opax-mcp-core (Cloud Run, us-central1) |
| ROOT_DOMAIN | vauco.no |
| HUB_URL | https://opax.vauco.no ✅ LIVE 2026-05-21 |
---
### DOMENEKONVENSJON — LOCKED
| Subdomain | Type | Formål |
|---|---|---|
| `opax.vauco.no` | Hub/MCP | OPAX-MCP operator hub — kun Vauco internt |
| `<klient>-os.vauco.no` | Prod OS | Kundens live produksjonssystem |
| `<klient>-oss.vauco.no` | Stage OS | Kundens staging/demo-system (pre-go-live) |
> `-os` = produksjon. `-oss` = staging. Aldri omvendt.
**Auth-strategi:**
- Nå: Google OAuth på alle miljøer
- Senere: BankID på `-os`-domener for kliniske kunder (Medioteq først)
**Kjente/planlagte domener:**
| Domene | Status | Cloud Run-tjeneste |
|---|---|---|
| `opax.vauco.no` | ✅ LIVE | `opax-mcp-core` |
| `medioteq-oss.vauco.no` | Planlagt | `medioteq-oss-core` |
| `medioteq-os.vauco.no` | Planlagt | `medioteq-os-core` |
---
### HITL-GATES — STOPP OG SPØR ALLTID
1. `DEPLOY GODKJENT` — før deploy til Cloud Run
2. `MERGE APPROVED` — før merge til main
3. `DEEP DREAM GODKJENT` — før strategisk vokabular eksponeres
4. `COST GODKJENT` — før endringer som påvirker billing
5. `IAM_GODKJENT` — før IAM-endringer eller ny service account
6. `NEWREPO` — før opprettelse av ny repo
---
### BOOT-PROTOKOLL — kjøres av ALLE tråder ved oppstart
1. **Connector-sjekk:** Er GitHub tilgjengelig?
- Ja → Les `docs/AGENT_RULEBOOK.md` direkte fra `OSVauco/main`
- Nei → Les denne filen (GDrive) + sjekk staleness-varsel øverst
2. Branch-discovery: list alle branches, finn mest aktiv (ahead av default)
- Hvis 1+ branch er 10+ commits ahead: STOPP og spør Chris
- Standard: `OSVauco/main` er canonical
3. Les eid fil + ROADMAP fra riktig branch
4. Bekreft i én linje: `Boot OK — branch X, HEAD Y, oppgave Z`
---
### EIERSKAP-MATRISE
| Fil | Eier | Andre kan |
|---|---|---|
| VAUCO_OS_MASTER_HANDOFF_v2.md | OPS | lese |
| VAUCO_OS_ROADMAP.md | PLAN | lese, foreslå patch via PR |
| SYSTEM_STATE_AGENT_BOOT.md | EXEC | lese |
| docs/AGENT_RULEBOOK.md | OPS | lese |
| docs/ARCHITECTURE.md | PLAN | lese, foreslå patch via PR |
| docs/LEARNINGS.md | OPS | lese, foreslå append |
| docs/RISKREGISTER.md | AUDIT | lese |
| docs/PLANBOARD.md | AUDIT | lese |
| CHANGELOG.md | OPS | lese |
| TODO.md | EXEC | lese |
| **docs/GDRIVE_MIRROR_BOOT.md** | **OPS** | lese |
---
### KOST-DISIPLIN
- $3/dag hard cap per tråd
- `gemini-2.5-flash` for enkle steg, `pro` for komplekse
- ALDRI rekursive modell-loops
- Hvis tråden bruker $1 på én oppgave: STOPP, rapporter, spør
---
### VOCABULARY FIREWALL
| Type | Ord | Regel |
|---|---|---|
| Offentlig (OK overalt) | Token Ledger, VVN, Provenance, File signature, Client identity record | Fritt bruk |
| Strategisk (KUN internt) | Pregeverdi, Deep Dream, Vauco-arv, Pregesignatur, T-konto | KUN i `deep-dream/`-mappe |
---
### KORREKSJONS-REGEL
Ground truth wins always.
1. Innrøm direkte i én setning
2. Oppdater eid fil med korreksjon
3. Fortsett
ALDRI forsvar gamle posisjoner.
---
## OPPDATERINGS-LOGG (append-only)
| Dato | Versjon | Endring | Synkronisert av |
|---|---|---|---|
| 2026-05-25 | v1.0 | Initial mirror av AGENT_RULEBOOK.md v1.2 + staleness-varsel + connector-guide | OPS-Computer-Hub |
| 2026-05-25 | v1.1 | Staleness-terskel endret fra 3 dager → 12 timer (aktiv dev-runde) | OPS-Computer-Hub |
---
*Neste gang AGENT_RULEBOOK.md endres: oppdater denne filen, endre tidsstempel i staleness-varselet, og last opp til GDrive.*
**EOF · GDRIVE_MIRROR_BOOT v1.1 · 2026-05-25 · OPS-Computer-Hub**

114
docs/GDRIVE_SETUP.md Normal file
View File

@ -0,0 +1,114 @@
# VAUCO OS — GDRIVE BACKUP SETUP
> Eier: OPS-Computer-Hub · Opprettet: 2026-05-25
Ett-gangs oppsett for å aktivere nattlig GDrive-backup og `sync-gdrive-mirror.sh`.
---
## Forutsetninger
- GCP service account med `roles/drive.file` på GDrive-mappen
- GitHub Secrets satt (se under)
- `rclone` installert lokalt for manuell bruk
---
## Steg 1 — Opprett GDrive-mapper
Opprett to mapper i Google Drive (under `chris.christiansen@vauco.no`):
| Mappe | Formål |
|---|---|
| `vauco-mirror/` | Nøkkelfiler (MD, indeks) — agent-lesbar |
| `vauco-backup/` | git bundle — disaster recovery |
Kopier mappe-ID fra URL: `https://drive.google.com/drive/folders/**<ID>**`
---
## Steg 2 — Service account (HITL: IAM_GODKJENT)
```bash
# Opprett service account
gcloud iam service-accounts create vauco-gdrive-backup \
--display-name="Vauco GDrive Backup" \
--project=propane-will-491900-m5
# Last ned nøkkel
gcloud iam service-accounts keys create /tmp/vauco-gdrive-sa.json \
--iam-account=vauco-gdrive-backup@propane-will-491900-m5.iam.gserviceaccount.com
```
Del `vauco-backup/`- og `vauco-mirror/`-mappene med service account-e-posten:
`vauco-gdrive-backup@propane-will-491900-m5.iam.gserviceaccount.com` (Editor)
---
## Steg 3 — GitHub Secrets
Gå til: `https://github.com/chrischristiansen-glitch/OSVauco/settings/secrets/actions`
Legg til:
| Secret | Verdi |
|---|---|
| `RCLONE_GDRIVE_SA_JSON` | Innhold av `/tmp/vauco-gdrive-sa.json` (hele JSON-strengen) |
| `GDRIVE_BACKUP_FOLDER_ID` | Mappe-ID for `vauco-backup/` fra GDrive URL |
---
## Steg 4 — Test manuelt
```bash
# Installer rclone lokalt
curl https://rclone.org/install.sh | sudo bash
# Konfigurer
rclone config # velg Google Drive, bruk service account JSON
# Test sync
bash scripts/sync-gdrive-mirror.sh
```
---
## Steg 5 — Aktiver workflow
Etter merge av PR #1:
- Workflow kjører automatisk neste natt kl 03:00 UTC
- Manuell trigger: GitHub → Actions → "Nightly GDrive Backup" → Run workflow
---
## Hva som synkroniseres
### `vauco-mirror/` (nøkkelfiler — agent-lesbar)
- `AGENT_RULEBOOK.md`
- `GDRIVE_MIRROR_BOOT.md` (auto-generert med tidsstempel)
- `LEARNINGS.md`
- `VAUCO_OS_ROADMAP.md`
- `TODO.md`
- `MASTERPLAN.md`
- `sessions/index.md`
### `vauco-backup/` (git bundle — disaster recovery)
- `OSVauco-backup-<timestamp>.bundle` — full repo med all historikk
- Beholder siste 7 bundles (ca. 1 uke)
---
## Gjenoppretting fra bundle
```bash
# Last ned bundle fra GDrive
# Klon fra bundle
git clone OSVauco-backup-2026-05-25T0300.bundle OSVauco-restored
cd OSVauco-restored
git remote set-url origin https://github.com/chrischristiansen-glitch/OSVauco.git
git push --mirror origin # MERGE APPROVED kreves
```
---
**EOF · GDRIVE_SETUP v1.0 · 2026-05-25 · OPS-Computer-Hub**

View File

@ -1,7 +1,7 @@
# OSVauco / OPAX TODO # OSVauco / OPAX TODO
> Managed by PLAN thread. Update when phases move between sections. > Managed by PLAN thread. Update when phases move between sections.
> Last updated: 2026-05-22 > Last updated: 2026-05-25
--- ---
@ -10,6 +10,16 @@
- [ ] **Phase 4** — Docs hardening: oppdater `LEARNINGS.md`, `SECRETS-SETUP.md`, `IAP-SETUP.md` med nåværende state. - [ ] **Phase 4** — Docs hardening: oppdater `LEARNINGS.md`, `SECRETS-SETUP.md`, `IAP-SETUP.md` med nåværende state.
- [ ] Verifiser at `source scripts/osvauco-opax-boot.sh` printer NESTE OPPGAVE i grønt (Cloud Shell). - [ ] Verifiser at `source scripts/osvauco-opax-boot.sh` printer NESTE OPPGAVE i grønt (Cloud Shell).
- [ ] Legg til `## SLUTTRAPPORT Phase 3` + `## NESTE OPPGAVE` blokk i `docs/OSVAUCO_OPAX_SESSION_LOG.md`. - [ ] Legg til `## SLUTTRAPPORT Phase 3` + `## NESTE OPPGAVE` blokk i `docs/OSVAUCO_OPAX_SESSION_LOG.md`.
- [ ] **GDrive backup — IAM-oppsett** (HITL: `IAM_GODKJENT` gitt 2026-05-25)
- Opprett service account: `vauco-gdrive-backup@propane-will-491900-m5.iam.gserviceaccount.com`
- Last ned JSON-nøkkel
- Del GDrive-mapper `vauco-mirror/` + `vauco-backup/` med service account (Editor)
- Se: `docs/GDRIVE_SETUP.md` for copy-paste-sekvens
- [ ] **GDrive backup — GitHub Secrets** (krever IAM-steget over)
- `RCLONE_GDRIVE_SA_JSON` — innhold av service account JSON
- `GDRIVE_BACKUP_FOLDER_ID` — mappe-ID for `vauco-backup/` fra GDrive URL
- Legg inn på: https://github.com/chrischristiansen-glitch/OSVauco/settings/secrets/actions
- [ ] **Første `mirror-sync`** — kjør etter merge for å opprette `.gdrive-mirror-state` og aktivere dashboard-status
--- ---
@ -19,6 +29,10 @@
- [ ] `opax-mcp/` restruktureres som ordentlig modul-subtree. - [ ] `opax-mcp/` restruktureres som ordentlig modul-subtree.
- [ ] Full boot cycle acceptance test (automatisert). - [ ] Full boot cycle acceptance test (automatisert).
- [ ] VS Code ↔ Cloud Shell workflow — preflight-script for lokal utvikling. - [ ] VS Code ↔ Cloud Shell workflow — preflight-script for lokal utvikling.
- [ ] **Gemini TUI-output logging**`script -a`-wrapper for `gemini`
- Alias `gemini-log` starter gemini inne i terminal-recorder
- `opax-logg-slutt` appender siste 50 linjer (stripped escape-koder) til session-log
- Gjør Gemini-dialog søkbar i `OSVAUCO_OPAX_SESSION_LOG.md`
--- ---
@ -29,6 +43,7 @@
- [ ] Multi-klient onboard-mønster (`<client>-oss-core` → `<client>-os-core`). - [ ] Multi-klient onboard-mønster (`<client>-oss-core` → `<client>-os-core`).
- [ ] OPS agent + BigQuery live logging. - [ ] OPS agent + BigQuery live logging.
- [ ] Green OSVauco-prompt med ANSI glow. - [ ] Green OSVauco-prompt med ANSI glow.
- [ ] Nattlig GDrive-backup aktiveres etter IAM + Secrets er satt opp.
--- ---
@ -44,3 +59,4 @@
- [x] **Phase 1**`MCP_NAME`, `MCP_PROTOCOL`, `ROOT_DOMAIN` locked; domenekonvensjon + klientmodell i `ARCHITECTURE.md`; `VAUCO_OS_ROADMAP.md` opprettet. - [x] **Phase 1**`MCP_NAME`, `MCP_PROTOCOL`, `ROOT_DOMAIN` locked; domenekonvensjon + klientmodell i `ARCHITECTURE.md`; `VAUCO_OS_ROADMAP.md` opprettet.
- [x] **Phase 2**`opax.vauco.no` LIVE: Cloud Run domain mapping + CNAME + SSL cert. `HUB_URL` locked. Boot-script peker på prod. - [x] **Phase 2**`opax.vauco.no` LIVE: Cloud Run domain mapping + CNAME + SSL cert. `HUB_URL` locked. Boot-script peker på prod.
- [x] **Phase 3** — Nemotron session loop i `.gemini/GEMINI.md`. `docs/TODO.md` opprettet. Phase 1+2 SLUTTRAPPORT i session log. - [x] **Phase 3** — Nemotron session loop i `.gemini/GEMINI.md`. `docs/TODO.md` opprettet. Phase 1+2 SLUTTRAPPORT i session log.
- [x] **GDrive/GitHub paritet**`GDRIVE_MIRROR_BOOT.md` + `sync-gdrive-mirror.sh` + nattlig backup-workflow + PROMPT_COMMAND terminal-logging (2026-05-25).

View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
# opax-logg-slutt.sh
# Standalone sluttlogg — fungerer selv om boot.sh ikke er sourcet.
# Bruk: bash ~/OSVauco/scripts/opax-logg-slutt.sh
# Eller legg alias i ~/.bashrc:
# alias opax-logg-slutt='bash ~/OSVauco/scripts/opax-logg-slutt.sh'
set -euo pipefail
OSVAUCO_DIR="${OSVAUCO_DIR:-$HOME/OSVauco}"
SESSION_LOG="$OSVAUCO_DIR/docs/OSVAUCO_OPAX_SESSION_LOG.md"
GREEN="$(tput setaf 2 2>/dev/null || echo '')"
YELLOW="$(tput setaf 3 2>/dev/null || echo '')"
NC="$(tput sgr0 2>/dev/null || echo '')"
if [[ ! -f "$SESSION_LOG" ]]; then
echo "[WARN] Session-logg ikke funnet: $SESSION_LOG"
echo " Kjør boot først: source ~/OSVauco/scripts/osvauco-opax-boot.sh"
exit 1
fi
printf "\n ${GREEN}Sesjonslogg — avslutt${NC}\n"
printf " Hva ble gjort? (LØST / ULØST)\n > "
read -r DONE_DESC
[[ -z "$DONE_DESC" ]] && DONE_DESC="(ingen notat)"
printf " Uløste problemer? (Enter for ingen)\n > "
read -r UNSOLVED
[[ -z "$UNSOLVED" ]] && UNSOLVED="ingen"
cat >> "$SESSION_LOG" << EOF
- Gjort : $DONE_DESC
- Uløst : $UNSOLVED
- Slutt : $(date '+%Y-%m-%d %H:%M %Z')
EOF
printf " ${GREEN}[OK]${NC} Logg oppdatert → %s\n\n" "$SESSION_LOG"

186
scripts/osvauco-opax-boot.sh Executable file → Normal file
View File

@ -1,14 +1,17 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ============================================================================= # =============================================================================
# osvauco-opax-boot.sh — OSVauco OPAX session-starter # osvauco-opax-boot.sh — OSVauco OPAX session-starter
# Manuell bruk: bash ~/OSVauco/scripts/osvauco-opax-boot.sh # Bruk: source ~/OSVauco/scripts/osvauco-opax-boot.sh
# IKKE i ~/.bashrc — det er boot.sh sin jobb # NB: Må sources (ikke bash) for PROMPT_COMMAND + opax-logg-slutt.
# Standalone avslutt: bash ~/OSVauco/scripts/opax-logg-slutt.sh
# ============================================================================= # =============================================================================
OSVAUCO_DIR="$HOME/OSVauco" OSVAUCO_DIR="$HOME/OSVauco"
ROADMAP="$OSVAUCO_DIR/docs/VAUCO_OS_ROADMAP.md" ROADMAP="$OSVAUCO_DIR/docs/VAUCO_OS_ROADMAP.md"
TODO="$OSVAUCO_DIR/docs/TODO.md" TODO="$OSVAUCO_DIR/docs/TODO.md"
SESSION_LOG="$OSVAUCO_DIR/docs/OSVAUCO_OPAX_SESSION_LOG.md" SESSION_LOG="$OSVAUCO_DIR/docs/OSVAUCO_OPAX_SESSION_LOG.md"
STATE_FILE="$OSVAUCO_DIR/.gdrive-mirror-state"
BASHRC="$HOME/.bashrc"
GREEN="$(tput setaf 2 || true)" GREEN="$(tput setaf 2 || true)"
RED="$(tput setaf 1 || true)" RED="$(tput setaf 1 || true)"
@ -25,14 +28,80 @@ FAIL="${RED}[XX]${NC}"
SESSION_ID="$(date '+%Y%m%d-%H%M%S')" SESSION_ID="$(date '+%Y%m%d-%H%M%S')"
# ============================================================================= # =============================================================================
# Load nvm so node/npm/gemini are on PATH even when script runs as subshell # ALIAS + PROMPT_COMMAND AUTO-INJECT i ~/.bashrc (idempotent)
# =============================================================================
_OSVAUCO_ALIAS_MARKER="# [OSVauco] auto-injected aliases"
if ! grep -qF "$_OSVAUCO_ALIAS_MARKER" "$BASHRC" 2>/dev/null; then
cat >> "$BASHRC" << 'ALIASES'
# [OSVauco] auto-injected aliases
alias opax='source ~/OSVauco/scripts/osvauco-opax-boot.sh'
alias opax-logg-slutt='bash ~/OSVauco/scripts/opax-logg-slutt.sh'
alias mirror-sync='bash ~/OSVauco/scripts/sync-gdrive-mirror.sh'
alias cost-audit='bash ~/OSVauco/scripts/cost-audit.sh'
alias roadmap='cat ~/OSVauco/docs/VAUCO_OS_ROADMAP.md'
alias session-log='cat ~/OSVauco/docs/OSVAUCO_OPAX_SESSION_LOG.md'
ALIASES
_ALIAS_INJECTED=true
else
_ALIAS_INJECTED=false
fi
# Last aliases inn i nåværende shell uansett
alias opax='source ~/OSVauco/scripts/osvauco-opax-boot.sh'
alias opax-logg-slutt='bash ~/OSVauco/scripts/opax-logg-slutt.sh'
alias mirror-sync='bash ~/OSVauco/scripts/sync-gdrive-mirror.sh'
alias cost-audit='bash ~/OSVauco/scripts/cost-audit.sh'
alias roadmap='cat ~/OSVauco/docs/VAUCO_OS_ROADMAP.md'
alias session-log='cat ~/OSVauco/docs/OSVAUCO_OPAX_SESSION_LOG.md'
# =============================================================================
# PROMPT_COMMAND — logger hver terminal-kommando med tidsstempel til session-log
# Aktiv så lenge dette shellet lever (ikke persistent — starter på nytt ved ny session)
# =============================================================================
export OSVAUCO_SESSION_LOG="$SESSION_LOG"
export OSVAUCO_SESSION_ID="$SESSION_ID"
_opax_last_cmd=''
# trap DEBUG fanger kommandoen FØR den kjøres
trap '_opax_last_cmd=$(history 1 | sed "s/^[ ]*[0-9]*[ ]*//")' DEBUG
# PROMPT_COMMAND kjøres etter hver kommando (ved neste prompt)
_opax_log_cmd() {
local exit_code=$?
local cmd="$_opax_last_cmd"
# Filtrer ut interne/støy-kommandoer
[[ -z "$cmd" ]] && return
[[ "$cmd" == _opax_* ]] && return
[[ "$cmd" == "trap "* ]] && return
local ts
ts=$(date '+%H:%M:%S')
local status_marker
if [[ $exit_code -eq 0 ]]; then
status_marker="✔"
else
status_marker="✘[$exit_code]"
fi
# Append til session-log (stille)
printf ' %s %s %s\n' "$ts" "$status_marker" "$cmd" >> "${OSVAUCO_SESSION_LOG}" 2>/dev/null || true
_opax_last_cmd=''
}
# Legg til i PROMPT_COMMAND (idempotent)
if [[ "${PROMPT_COMMAND}" != *"_opax_log_cmd"* ]]; then
PROMPT_COMMAND="_opax_log_cmd${PROMPT_COMMAND:+; $PROMPT_COMMAND}"
fi
export PROMPT_COMMAND
# =============================================================================
# Load nvm
# ============================================================================= # =============================================================================
export NVM_DIR="$HOME/.nvm" export NVM_DIR="$HOME/.nvm"
# shellcheck source=/dev/null
[[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh" [[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
# Also check common system paths for gemini (e.g. symlinked to /usr/local/bin)
if ! command -v gemini &>/dev/null && [[ -d "$NVM_DIR" ]]; then if ! command -v gemini &>/dev/null && [[ -d "$NVM_DIR" ]]; then
# nvm may not auto-select a version in non-interactive shells
NVM_DEFAULT=$(nvm version default 2>/dev/null || true) NVM_DEFAULT=$(nvm version default 2>/dev/null || true)
[[ -n "$NVM_DEFAULT" ]] && nvm use "$NVM_DEFAULT" &>/dev/null || true [[ -n "$NVM_DEFAULT" ]] && nvm use "$NVM_DEFAULT" &>/dev/null || true
fi fi
@ -56,7 +125,6 @@ printf " ----------------------------------------------------\n\n"
# ============================================================================= # =============================================================================
printf "${BOLD}${CYAN} [ AUTH ]${NC}\n" printf "${BOLD}${CYAN} [ AUTH ]${NC}\n"
# .env
if [[ -f "$OSVAUCO_DIR/.env" ]]; then if [[ -f "$OSVAUCO_DIR/.env" ]]; then
set -o allexport; source "$OSVAUCO_DIR/.env"; set +o allexport set -o allexport; source "$OSVAUCO_DIR/.env"; set +o allexport
printf " $OK .env ${DIM}PROJECT_ID=${PROJECT_ID}${NC}\n" printf " $OK .env ${DIM}PROJECT_ID=${PROJECT_ID}${NC}\n"
@ -64,7 +132,6 @@ else
printf " $FAIL .env MISSING ${YELLOW}cp .env.example .env${NC}\n" printf " $FAIL .env MISSING ${YELLOW}cp .env.example .env${NC}\n"
fi fi
# gcloud
if gcloud auth print-access-token >/dev/null 2>&1; then if gcloud auth print-access-token >/dev/null 2>&1; then
ACCOUNT=$(gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null) ACCOUNT=$(gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null)
printf " $OK gcloud ${DIM}%s${NC}\n" "$ACCOUNT" printf " $OK gcloud ${DIM}%s${NC}\n" "$ACCOUNT"
@ -72,14 +139,12 @@ else
printf " $FAIL gcloud ${YELLOW}gcloud auth login --no-launch-browser${NC}\n" printf " $FAIL gcloud ${YELLOW}gcloud auth login --no-launch-browser${NC}\n"
fi fi
# ADC
if gcloud auth application-default print-access-token >/dev/null 2>&1; then if gcloud auth application-default print-access-token >/dev/null 2>&1; then
printf " $OK ADC ${DIM}Application Default Credentials OK${NC}\n" printf " $OK ADC ${DIM}Application Default Credentials OK${NC}\n"
else else
printf " $WARN ADC ${YELLOW}gcloud auth application-default login${NC}\n" printf " $WARN ADC ${YELLOW}gcloud auth application-default login${NC}\n"
fi fi
# GitHub CLI
if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
GH_USER=$(gh api user --jq .login 2>/dev/null || echo "ukjent") GH_USER=$(gh api user --jq .login 2>/dev/null || echo "ukjent")
printf " $OK GitHub CLI ${DIM}gh → %s${NC}\n" "$GH_USER" printf " $OK GitHub CLI ${DIM}gh → %s${NC}\n" "$GH_USER"
@ -87,14 +152,21 @@ else
printf " $WARN GitHub CLI ${YELLOW}gh auth login (valgfritt)${NC}\n" printf " $WARN GitHub CLI ${YELLOW}gh auth login (valgfritt)${NC}\n"
fi fi
# Gemini CLI
if command -v gemini &>/dev/null; then if command -v gemini &>/dev/null; then
GEMINI_VER=$(gemini --version 2>/dev/null || echo "ukjent") GEMINI_VER=$(gemini --version 2>/dev/null || echo "ukjent")
printf " $OK Gemini CLI ${DIM}%s${NC}\n" "$GEMINI_VER" printf " $OK Gemini CLI ${DIM}%s${NC}\n" "$GEMINI_VER"
else else
printf " $WARN Gemini CLI ${YELLOW}Ikke installert — kjør: npm install -g @google/gemini-cli${NC}\n" printf " $WARN Gemini CLI ${YELLOW}npm install -g @google/gemini-cli${NC}\n"
fi fi
if [[ "$_ALIAS_INJECTED" == true ]]; then
printf " $OK Aliases ${DIM}Lagt til i ~/.bashrc (aktiv nå)${NC}\n"
else
printf " $OK Aliases ${DIM}Allerede i ~/.bashrc${NC}\n"
fi
printf " $OK Terminal-logging ${DIM}PROMPT_COMMAND aktiv — loggfører alle kommandoer${NC}\n"
printf "\n" printf "\n"
@ -112,24 +184,68 @@ printf "\n"
# ============================================================================= # =============================================================================
# SECTION 3: NESTE OPPGAVE (fra ROADMAP + TODO) # SECTION 3: REPO SYNC + GDRIVE MIRROR
# =============================================================================
printf "${BOLD}${CYAN} [ REPO SYNC ]${NC}\n"
LOCAL_SHA=$(git -C "$OSVAUCO_DIR" rev-parse --short HEAD 2>/dev/null || echo "ukjent")
LOCAL_BRANCH=$(git -C "$OSVAUCO_DIR" branch --show-current 2>/dev/null || echo "ukjent")
REMOTE_SHA=$(git -C "$OSVAUCO_DIR" ls-remote origin refs/heads/main 2>/dev/null | cut -c1-7 || echo "")
if [[ -z "$REMOTE_SHA" ]]; then
printf " $WARN GitHub HEAD ${YELLOW}Kunne ikke nå GitHub (offline?)${NC}\n"
printf " ${DIM}Lokal: %s @ %s${NC}\n" "$LOCAL_SHA" "$LOCAL_BRANCH"
elif [[ "$LOCAL_SHA" == "$REMOTE_SHA" ]]; then
printf " $OK GitHub ≡ Lokal ${DIM}HEAD %s @ %s — ingen diff${NC}\n" "$LOCAL_SHA" "$LOCAL_BRANCH"
else
printf " $WARN GitHub ≠ Lokal ${YELLOW}GitHub: %s │ Lokal: %s @ %s${NC}\n" "$REMOTE_SHA" "$LOCAL_SHA" "$LOCAL_BRANCH"
printf " ${DIM}Kjør: git pull origin main${NC}\n"
fi
printf "\n"
printf "${BOLD}${CYAN} [ GDRIVE MIRROR ]${NC}\n"
if [[ -f "$STATE_FILE" ]]; then
LAST_SYNC=$(grep '^LAST_SYNC=' "$STATE_FILE" | cut -d= -f2-)
LAST_SHA=$(grep '^LAST_SHA=' "$STATE_FILE" | cut -d= -f2-)
SYNC_EPOCH=$(date -d "${LAST_SYNC}" '+%s' 2>/dev/null \
|| date -j -f '%Y-%m-%dT%H:%M %Z' "${LAST_SYNC}" '+%s' 2>/dev/null \
|| echo 0)
NOW_EPOCH=$(date '+%s')
AGE_HOURS=$(( (NOW_EPOCH - SYNC_EPOCH) / 3600 ))
AGE_MIN=$(( (NOW_EPOCH - SYNC_EPOCH) / 60 % 60 ))
if [[ "$LAST_SHA" != "$LOCAL_SHA" ]]; then
printf " $FAIL GDrive mirror ${RED}UTDATERT — SHA endret (%s → %s)${NC}\n" "$LAST_SHA" "$LOCAL_SHA"
printf " ${YELLOW}Kjør: mirror-sync${NC}\n"
elif [[ "$AGE_HOURS" -ge 12 ]]; then
printf " $FAIL GDrive mirror ${RED}GAMMEL — %st %sm siden sist sync${NC}\n" "$AGE_HOURS" "$AGE_MIN"
printf " ${YELLOW}Kjør: mirror-sync${NC}\n"
elif [[ "$AGE_HOURS" -ge 8 ]]; then
printf " $WARN GDrive mirror ${YELLOW}%st %sm siden sist sync (terskel 12t)${NC}\n" "$AGE_HOURS" "$AGE_MIN"
printf " ${DIM}Vurder: mirror-sync${NC}\n"
else
printf " $OK GDrive mirror ${DIM}%s · HEAD %s${NC}\n" "$LAST_SYNC" "$LAST_SHA"
fi
else
printf " $WARN GDrive mirror ${YELLOW}Aldri synkronisert — kjør: mirror-sync${NC}\n"
fi
printf "\n"
# =============================================================================
# SECTION 4: NESTE OPPGAVE
# ============================================================================= # =============================================================================
printf "${BOLD}${CYAN} [ NESTE OPPGAVE ]${NC}\n" printf "${BOLD}${CYAN} [ NESTE OPPGAVE ]${NC}\n"
# Hent første ugjorte oppgave under ## NEXT fra ROADMAP
if [[ -f "$ROADMAP" ]]; then if [[ -f "$ROADMAP" ]]; then
NEXT_ROADMAP=$(awk '/^## NEXT/{f=1;next} f && /^## /{f=0} f && /^- \[ \]/{print;exit}' "$ROADMAP") NEXT_ROADMAP=$(awk '/^## NEXT/{f=1;next} f && /^## /{f=0} f && /^- \[ \]/{print;exit}' "$ROADMAP")
if [[ -n "$NEXT_ROADMAP" ]]; then if [[ -n "$NEXT_ROADMAP" ]]; then
printf " ${GREEN}${BOLD}▶ ROADMAP NEXT:${NC}\n" printf " ${GREEN}${BOLD}▶ ROADMAP NEXT:${NC}\n"
printf " ${GREEN}%s${NC}\n" "$NEXT_ROADMAP" printf " ${GREEN}%s${NC}\n" "$NEXT_ROADMAP"
else
printf " ${DIM}(ingen åpne punkt under ## NEXT i ROADMAP)${NC}\n"
fi fi
else
printf " ${WARN} ROADMAP ikke funnet: %s\n" "$ROADMAP"
fi fi
# Hent åpne punkter fra TODO.md (maks 3)
if [[ -f "$TODO" ]]; then if [[ -f "$TODO" ]]; then
TODO_ITEMS=$(grep -m3 '^- \[ \]' "$TODO" 2>/dev/null || true) TODO_ITEMS=$(grep -m3 '^- \[ \]' "$TODO" 2>/dev/null || true)
if [[ -n "$TODO_ITEMS" ]]; then if [[ -n "$TODO_ITEMS" ]]; then
@ -139,12 +255,11 @@ if [[ -f "$TODO" ]]; then
done <<< "$TODO_ITEMS" done <<< "$TODO_ITEMS"
fi fi
fi fi
printf "\n" printf "\n"
# ============================================================================= # =============================================================================
# SECTION 4: SESSION-LOGG # SECTION 5: SESSION-LOGG START
# ============================================================================= # =============================================================================
mkdir -p "$(dirname "$SESSION_LOG")" mkdir -p "$(dirname "$SESSION_LOG")"
@ -161,10 +276,15 @@ cat >> "$SESSION_LOG" << EOF
- Tid : $(date '+%Y-%m-%d %H:%M %Z') - Tid : $(date '+%Y-%m-%d %H:%M %Z')
- Bruker : ${ACCOUNT:-ukjent} - Bruker : ${ACCOUNT:-ukjent}
- OPAX : $(curl -fsS --max-time 3 "https://opax.vauco.no/ping" >/dev/null 2>&1 && echo OK || echo NEDE) - OPAX : $(curl -fsS --max-time 3 "https://opax.vauco.no/ping" >/dev/null 2>&1 && echo OK || echo NEDE)
- Lokal : $LOCAL_SHA @ $LOCAL_BRANCH
- Remote : ${REMOTE_SHA:-ukjent}
- Mål : $SESSION_DESC - Mål : $SESSION_DESC
### Kommandologg
EOF EOF
printf " $OK Logg startet ${DIM}→ docs/OSVAUCO_OPAX_SESSION_LOG.md${NC}\n\n" printf " $OK Logg startet ${DIM}→ docs/OSVAUCO_OPAX_SESSION_LOG.md${NC}\n"
printf " ${DIM}Alle kommandoer loggføres automatisk med tidsstempel + exit-kode.${NC}\n\n"
# ============================================================================= # =============================================================================
@ -172,27 +292,34 @@ printf " $OK Logg startet ${DIM}→ docs/OSVAUCO_OPAX_SESSION_LOG.md${NC}\
# ============================================================================= # =============================================================================
printf "${DIM} ---------------------------------------------------${NC}\n" printf "${DIM} ---------------------------------------------------${NC}\n"
printf " ${CYAN}${BOLD}HURTIGKOMMANDOER${NC}\n" printf " ${CYAN}${BOLD}HURTIGKOMMANDOER${NC}\n"
printf " ${DIM}opax${NC} → ny session (source boot på nytt)\n"
printf " ${DIM}gemini${NC} → Gemini TUI (OPAX-MCP)\n" printf " ${DIM}gemini${NC} → Gemini TUI (OPAX-MCP)\n"
printf " ${DIM}cost-audit${NC} → bash scripts/cost-audit.sh\n" printf " ${DIM}cost-audit${NC} → bash scripts/cost-audit.sh\n"
printf " ${DIM}roadmap${NC} → cat docs/VAUCO_OS_ROADMAP.md\n" printf " ${DIM}roadmap${NC} → cat docs/VAUCO_OS_ROADMAP.md\n"
printf " ${DIM}session-log${NC} → cat docs/OSVAUCO_OPAX_SESSION_LOG.md\n" printf " ${DIM}session-log${NC} → cat docs/OSVAUCO_OPAX_SESSION_LOG.md\n"
printf " ${DIM}mirror-sync${NC} → bash scripts/sync-gdrive-mirror.sh\n"
printf " ${DIM}opax-logg-slutt${NC} → avslutt og loggfør session\n"
printf "${DIM} ---------------------------------------------------${NC}\n\n" printf "${DIM} ---------------------------------------------------${NC}\n\n"
# ============================================================================= # =============================================================================
# AVSLUTT-HOOK # AVSLUTT-FUNKSJON
# ============================================================================= # =============================================================================
opax-logg-slutt() { opax-logg-slutt() {
# Deaktiver PROMPT_COMMAND-logging for denne sesjonen
PROMPT_COMMAND="${PROMPT_COMMAND//_opax_log_cmd; /}"
PROMPT_COMMAND="${PROMPT_COMMAND//_opax_log_cmd/}"
printf "\n ${BOLD}${CYAN}Sesjonslogg — avslutt${NC}\n" printf "\n ${BOLD}${CYAN}Sesjonslogg — avslutt${NC}\n"
printf " Hva ble gjort? (LØST / ULØST)\n > " printf " Hva ble gjort? (LØST / ULØST)\n > "
read -r DONE_DESC read -r DONE_DESC
[[ -z "$DONE_DESC" ]] && DONE_DESC="(ingen notat)" [[ -z "$DONE_DESC" ]] && DONE_DESC="(ingen notat)"
printf " Uløste problemer? (Enter for ingen)\n > " printf " Uløste problemer? (Enter for ingen)\n > "
read -r UNSOLVED read -r UNSOLVED
[[ -z "$UNSOLVED" ]] && UNSOLVED="ingen" [[ -z "$UNSOLVED" ]] && UNSOLVED="ingen"
cat >> "$SESSION_LOG" << EOF cat >> "$SESSION_LOG" << EOF
### Sesjonsavslutning
- Gjort : $DONE_DESC - Gjort : $DONE_DESC
- Uløst : $UNSOLVED - Uløst : $UNSOLVED
- Slutt : $(date '+%Y-%m-%d %H:%M %Z') - Slutt : $(date '+%Y-%m-%d %H:%M %Z')
@ -200,7 +327,8 @@ EOF
printf " ${GREEN}[OK]${NC} Logg oppdatert → docs/OSVAUCO_OPAX_SESSION_LOG.md\n\n" printf " ${GREEN}[OK]${NC} Logg oppdatert → docs/OSVAUCO_OPAX_SESSION_LOG.md\n\n"
} }
export -f opax-logg-slutt 2>/dev/null || true export -f opax-logg-slutt 2>/dev/null || true
printf " ${DIM}Når du er ferdig → skriv: ${NC}${BOLD}opax-logg-slutt${NC}\n\n"
printf " ${DIM}Avslutt session → ${NC}${BOLD}opax-logg-slutt${NC}\n\n"
# ============================================================================= # =============================================================================
@ -212,12 +340,6 @@ case "$ANSWER" in
echo echo
if ! command -v gemini &>/dev/null; then if ! command -v gemini &>/dev/null; then
printf " ${RED}[XX]${NC} gemini ikke funnet.\n" printf " ${RED}[XX]${NC} gemini ikke funnet.\n"
printf " Installer med:\n"
printf " curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash\n"
printf " export NVM_DIR=\"\$HOME/.nvm\" && source \"\$NVM_DIR/nvm.sh\"\n"
printf " nvm install --lts\n"
printf " npm install -g @google/gemini-cli\n"
printf " ln -sf \$(which gemini) /usr/local/bin/gemini\n"
else else
echo " [OSVauco] Starter Gemini-CLI fra ~/OSVauco..." echo " [OSVauco] Starter Gemini-CLI fra ~/OSVauco..."
cd "$OSVAUCO_DIR" cd "$OSVAUCO_DIR"

View File

@ -0,0 +1,101 @@
#!/usr/bin/env bash
# sync-gdrive-mirror.sh
# Oppdaterer docs/GDRIVE_MIRROR_BOOT.md med fersk indeks + tidsstempel.
# Skriver .gdrive-mirror-state for å vise status i boot-dashboard.
# Kjøres manuelt: bash scripts/sync-gdrive-mirror.sh
set -euo pipefail
REPO_ROOT="$(git rev-parse --show-toplevel)"
OUTPUT="$REPO_ROOT/docs/GDRIVE_MIRROR_BOOT.md"
STATE_FILE="$REPO_ROOT/.gdrive-mirror-state"
TIMESTAMP=$(date '+%Y-%m-%dT%H:%M %Z')
SHA=$(git rev-parse --short HEAD)
echo "[sync-gdrive-mirror] Tidsstempel: $TIMESTAMP · HEAD: $SHA"
# ── Bygg header + staleness-varsel ─────────────────────────────────────────
cat > "$OUTPUT" << HEADER
# VAUCO OS — GDRIVE MIRROR BOOT
> **CONNECTOR-PRIORITET:**
> \`\`\`
> GITHUB > GOOGLE DRIVE
> \`\`\`
> GitHub (\`OSVauco/main/docs/AGENT_RULEBOOK.md\`) er **alltid** ground truth.
> Denne filen er auto-generert av \`sync-gdrive-mirror.sh\`.
> Ved enhver konflikt: stol på GitHub. Oppdater ved å kjøre scriptet på nytt.
---
## ⚠️ STALENESS-VARSEL — LES DETTE FØRST
\`\`\`
╔══════════════════════════════════════════════════════════════╗
║ SIST SYNKRONISERT: $TIMESTAMP
║ HEAD: $SHA
║ Kilde: OSVauco/main · Synkronisert av: sync-gdrive-mirror.sh ║
╠══════════════════════════════════════════════════════════════╣
║ ⚠️ TERSKEL: 12 TIMER (aktiv dev-runde)
║ HVIS MER ENN 12T HAR GÅTT: STOPP og verifiser mot GitHub ║
╠══════════════════════════════════════════════════════════════╣
║ VERIFISER: https://github.com/chrischristiansen-glitch/ ║
║ OSVauco/blob/main/docs/AGENT_RULEBOOK.md ║
╚══════════════════════════════════════════════════════════════╝
\`\`\`
---
## PROSJEKTINDEKS — AUTO-GENERERT $TIMESTAMP · HEAD $SHA
HEADER
# ── Legg inn TODO ──────────────────────────────────────────────────────────
if [[ -f "$REPO_ROOT/docs/TODO.md" ]]; then
echo -e "\n---\n\n## TODO\n" >> "$OUTPUT"
cat "$REPO_ROOT/docs/TODO.md" >> "$OUTPUT"
fi
if [[ -f "$REPO_ROOT/protocols/sessions/index.md" ]]; then
echo -e "\n---\n\n## SESJONSLOGG\n" >> "$OUTPUT"
cat "$REPO_ROOT/protocols/sessions/index.md" >> "$OUTPUT"
fi
if [[ -f "$REPO_ROOT/docs/VAUCO_OS_ROADMAP.md" ]]; then
echo -e "\n---\n\n## ROADMAP\n" >> "$OUTPUT"
cat "$REPO_ROOT/docs/VAUCO_OS_ROADMAP.md" >> "$OUTPUT"
fi
if [[ -f "$REPO_ROOT/docs/AGENT_RULEBOOK.md" ]]; then
echo -e "\n---\n\n## AGENT_RULEBOOK\n" >> "$OUTPUT"
cat "$REPO_ROOT/docs/AGENT_RULEBOOK.md" >> "$OUTPUT"
fi
if [[ -f "$REPO_ROOT/docs/LEARNINGS.md" ]]; then
echo -e "\n---\n\n## LEARNINGS — siste oppføringer\n" >> "$OUTPUT"
tail -60 "$REPO_ROOT/docs/LEARNINGS.md" >> "$OUTPUT"
fi
# ── Footer ────────────────────────────────────────────────────────────────
cat >> "$OUTPUT" << FOOTER
---
*Oppdater ved å kjøre: \`bash scripts/sync-gdrive-mirror.sh\` — last deretter opp til GDrive.*
**EOF · GDRIVE_MIRROR_BOOT · $TIMESTAMP · HEAD $SHA · auto-generert**
FOOTER
# ── Skriv state-fil (for boot-dashboard) ───────────────────────────────
cat > "$STATE_FILE" << STATE
LAST_SYNC=$TIMESTAMP
LAST_SHA=$SHA
STATE
# ── Commit + push ─────────────────────────────────────────────────────────
cd "$REPO_ROOT"
git add docs/GDRIVE_MIRROR_BOOT.md .gdrive-mirror-state
git commit -m "chore(docs): sync GDRIVE_MIRROR_BOOT $TIMESTAMP [HEAD $SHA]"
git push origin main
echo "[sync-gdrive-mirror] Ferdig. Last ned docs/GDRIVE_MIRROR_BOOT.md og erstatt i GDrive."