Files
ds-galo/AGENTS.md
T
iu 863038b5a0 chore: добавить AGENTS.md с инструкциями для агентов
Правила работы в репозитории: команды, архитектура, миграции, конфигурация,
фронтенд, OpenSpec и конвенции коммитов. Отдельный раздел про прогоны с
эмулятором: instrumented-тесты и запуск AVD могут зависнуть, прогресс нужно
проверять примерно раз в минуту, а не ждать молча.
2026-10-16 13:28:03 +03:00

9.3 KiB
Raw Blame History

AGENTS.md

Инструкции для агентов, работающих в этом репозитории. Читай вместе с README.md (актуальный источник правды) и project.md (исходное ТЗ).

Что это

Self-hosted фотоальбом: Go-бэкенд с вшитой через go:embed статикой SvelteKit, один статический бинарник (CGO_ENABLED=0), без Docker. Плюс отдельный Android-клиент.

По умолчанию (DB_BACKEND=sqlite, STORAGE_BACKEND=fs) работает полностью локально, без Postgres и S3. Postgres/Garage (pg.localnet, s3.localnet) — опциональные слои.

Команды

Все команды — из корня репозитория. Голый make только печатает список целей.

make build        # frontend -> backend/static -> go:embed -> bin/galo
make frontend     # npm run build (инкрементально), копирует статику в backend/static
make backend      # CGO_ENABLED=0 go build -tags nodynamic -o ../bin/galo
make run          # frontend + backend + запуск ./bin/galo
make migrate      # применяет только Postgres-миграции (cmd/migrate)
make test         # cd backend && go test ./...  (только бэкенд!)
make testdata     # наполняет запущенный инстанс через scripts/seed.py
make android      # cd android && ./gradlew :app:assembleDebug
make install-android-app  # сборка + установка debug-APK на устройство
  • -tags nodynamic обязателен: без него gen2brain/webp тянет динамический libwebp и бинарник перестаёт быть статическим.
  • Порядок сборки важен: frontend должен отработать до backend, иначе go:embed all:static вшивает только backend/static/.gitkeep и бинарник выходит без UI.
  • make test не запускает фронтенд-тесты; отдельных make-целей для них нет: cd frontend && npm run test (vitest, окружение node, файлы src/**/*.test.ts) и cd frontend && npm run check (svelte-check/typecheck).
  • Один Go-тест: cd backend && go test ./internal/photos/ -run TestName -v.
  • Интеграционные тесты Postgres-репозиториев пропускаются без TEST_DATABASE_URL: TEST_DATABASE_URL='postgres://user:pass@pg.localnet:5432/galo?sslmode=disable' \ cd backend && go test ./internal/repo/ -v
  • Тесты видео (internal/e2e) сами пропускаются, если нет ffmpeg/ffprobe. Тесты e2e репозиториев поднимают SQLite в t.TempDir() и внешних сервисов не требуют.

Тесты на эмуляторе

Instrumented-прогоны (:app:connectedDebugAndroidTest) и сам запуск AVD могут зависнуть — не дожидайся их молча. Пока идёт прогон, проверяй прогресс примерно раз в минуту: жив ли процесс, обновляются ли результаты, отвечает ли устройство:

pgrep -fa "GradleWrapperMain|Gradle Test Executor"
ls -la android/app/build/outputs/androidTest-results/connected/debug/
adb devices

Если прогресса нет дольше пары минут — снимай прогон (kill), а не жди дальше, и разбирайся по дампу потоков (jstack <pid> JVM тестов). То же относится к обычным unit-тестам: они тоже идут в отдельной JVM, и её зависание видно только по тому, что результаты перестали обновляться.

Архитектура

  • Go-модуль galo (backend/go.mod, Go 1.26). Точки входа: backend/cmd/server, cmd/migrate, cmd/reconcile, cmd/backfill-exif.
  • Доменные пакеты в backend/internal/<domain> (albums, auth, members, photos, social, notifications, sharelinks, storage, sse, settings, video). Каждый содержит сервис, HTTP-обработчики и Repository-интерфейс.
  • internal/store/store.go — единственное место, которое знает конкретные реализации. При добавлении метода в Repository нужно реализовать его в обоих вариантах: Postgres (NewStore/NewPostgres) и SQLite (NewSQLiteStore/NewSQLite).
  • backend/internal/app — маршруты/статика; internal/repo/contract — контрактные тесты, которые гоняют одинаковый набор проверок для SQLite и Postgres.
  • backend/embed.go вшивает static (фронтенд) и migrations/**. Паттерны эмбеда — migrations/*.sql migrations/sqlite/*.sql: новые файлы должны им соответствовать.
  • Права проверяются на уровне сервиса, не только в UI. Блобы наружу отдаются только через бэкенд: GET /api/objects/<key> с HMAC-подписью, один маршрут для авторизованных и для share-ссылок. Ключи объектов непрозрачны: objects/{object_id}/{role}.
  • SSE (/api/sse/...) авторизуется через ?token=, т.к. EventSource не шлёт заголовки. Для nginx критичен proxy_buffering off.
  • android/ — самостоятельный Gradle-модуль, серверный и веб-код не трогает; использует уже существующий HTTP API. Тесты: cd android && ./gradlew test.

Миграции (частый источник ошибок)

Схема поддерживается в двух диалектах с независимой нумерацией:

  • Postgres: backend/migrations/NNNNNN_*.{up,down}.sql
  • SQLite: backend/migrations/sqlite/NNNNNN_*.{up,down}.sql

Любое изменение схемы нужно добавить в оба каталога, номера версий не обязаны совпадать (сейчас они разошлись). Миграции вшиты в бинарник и применяются автоматически при старте сервера для выбранного бэкенда. make migrate применяет только Postgres. cmd/reconcile существует для сверки хранилища с журналом objects (сборка мусора журналом управляется и хранилище не сканирует).

Конфигурация и данные

  • .env читается вручную в cmd/*/main.go из .env, затем ../.env (без dotenv-библиотеки).
  • Секреты подписи JWT и URL объектов не задаются в env: генерируются при первом старте и лежат в слое метаданных (app_settings), поэтому переживают перезапуск и рестарт SQLite.
  • Локальные артефакты в корне (galo.db*, /data/, bin/, backend/static/*, frontend/build/) в git не попадают — не коммить их.

Фронтенд

  • SvelteKit 2 + Svelte 5 (runes), adapter-static с fallback: index.html, Tailwind v4.
  • Тёмная/светлая/нейтральная темы через data-theme на <html> и семантические CSS-токены. В компонентах — только семантические классы (bg-bg-elevated, text-muted и т.п.), никаких dark: префиксов.
  • Vite dev-сервер проксирует /api на localhost:8080 (см. vite.config.ts).

OpenSpec

Спецификации — в openspec/specs/<capability>/spec.md; завершённые изменения — в openspec/changes/archive/<YYYY-MM-DD-name>. Активных изменений сейчас нет. Workflow-команды и скиллы лежат в .opencode/ и требуют CLI openspec (в этом окружении он может быть не установлен — проверь command -v openspec). При изменении поведения сначала обновляй/создавай спеку, а не только код.

Конвенции репозитория

  • Ветка develop; коммиты — Conventional Commits с русским описанием (feat(realtime): ..., test(android): ..., chore: ...). Функциональные ветки вливаются в develop через merge-коммиты.
  • project.md — исходное ТЗ и местами устарел (например, называет S3 бэкендом по умолчанию и старую раскладку ключей albums/...). Ориентируйся на README.md и код.