# Goon Self-hosted aggregator of adult-content scene metadata. Multi-source ingest (TPDB, StashDB, 30+ tubes) → dedup → on-demand stream resolution (yt-dlp + JWPlayer unpacker) → API + Expo mobile client. Stack: Python 3.12 (FastAPI + SQLAlchemy + Alembic), Postgres 16, React Native (Expo), Docker Compose. Git: github.com/goon-foss/goon (remote: `goonfoss`). Public OSS repo. 18+ — see `DISCLAIMER.md`. --- ## Zmiany mobilne (Expo) → publikuj przez OTA, nie zostawiaj w gicie Klient `mobile/` (React Native + Expo) aktualizuje się przez **self-hosted Expo Updates (OTA)**, nie przez sklep ani rebuild APK. Zmiany JS (ekrany, komponenty, `api.ts`) lecą silent. **KRYTYCZNE: `git commit` NIE publikuje OTA.** Sam commit (ani push) nie zmienia NIC na telefonie. Po zmianie w `mobile/` trzeba zbudować bundle i opublikować: ``` # z roota repo; konkretne wartości env w .env.local / prywatnej pamięci (NIE hardcoduj IP tutaj) GOON_VPS_SSH= GOON_VPS_UPDATES_DIR=/root/goon/app/static/expo-updates \ GOON_PUBLIC_UPDATES_URL=https://api.goon-foss.org/expo-updates/asset \ python scripts/publish_update.py --runtime 1.1 ``` Skrypt: `expo export` (build) → scp bundla na VPS pod `app/static/expo-updates///` → przełącza `current.json` (endpoint `GET /expo-updates/manifest` serwuje aktywny). Apka pobiera przy następnym launchu. Reguły: - **runtime = `1.1`** (== `runtimeVersion` w `app.json`/APK). Bump TYLKO przy native change (wtedy też nowy APK przez PackageInstaller). `RUNTIME_DEFAULT` w skrypcie = 1.1. - **Apply dwustopniowy**: 1. launch pobiera w tle, 2. launch aplikuje → po publish **restart apki 2×**. - **Publish odpala AI** (nie człowiek, nie git-hook). Skrypt działa one-shot też na Windows git-bash (fix 2026-06-02: scp source `.`+`cwd=DIST`, `MSYS_NO_PATHCONV`, defensywne odkręcanie zmanglowanej ścieżki). - **Backend (`app/`) to OSOBNY deploy** — scp `app/`→VPS + `docker compose restart` (worker/api). NIE przez OTA. `./app` i `./scripts` są wolumenami w compose, więc restart wystarcza (bez rebuildu obrazu). --- ## Kanban (auto-aggregation) Ten workspace ma własny Kanban (custom tracker type `kanban` w `.nimbalyst/trackers/kanban.yaml`) z kolumnami: **Backlog → Następne → W trakcie → Czeka → Zrobione** ### Reguła auto-agregacji — WAŻNE Kiedy podczas sesji pojawi się nowy temat / bug / pomysł / blocker, na który **nie ma teraz czasu** lub jest poboczny względem aktualnego zadania — **utwórz tracker item** zamiast tylko wspomnieć o nim w czacie: ``` mcp__nimbalyst-mcp__tracker_create( type: "kanban", title: "", status: "backlog", description: "<1-2 zdania kontekstu + ścieżka pliku jeśli dotyczy>" ) ``` Powód: Jan często skupia się na pierwszej rzeczy z planu, a pozostałe znikają. Kanban jest gwarancją, że nic nie wypadnie. Jeśli wspomnisz coś w czacie i nie założysz ticketu — to się zgubi. Status `next` = "wybrane na najbliższe dni" (3-5 max). `waiting` = zablokowane na zewnętrzne. `done` ustawia użytkownik, nigdy AI.