gendesign/README.md
2026-05-11 13:43:15 +03:00

205 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Generative Design + Site Finder
Две продуктовые линии в одной воронке: **Site Finder** (AI-подбор инвестиционных земельных участков) + **Generative Design** (автоматическая генерация концепций застройки) для девелоперов РФ. Целевой регион Discovery — Свердловская обл. (ЕКБ, ПЗЗ, МСК-66).
## North Star
К концу месяца 3: **3 платящих пилота** (≥30 тыс. ₽/мес каждый) + заявка в реестр российского ПО → право на Раунд А (2025 млн ₽).
---
## Текущий статус (май 2026)
**Live:** [https://gendsgn.ru/](https://gendsgn.ru/) — HTTP/2+HTTP/3, валидный TLS, [/health](https://gendsgn.ru/health) `{"status":"ok"}`. Полный CI/CD: GitHub Actions → GHCR → SSH-deploy на Beget VPS. Sentry активен (release tracking привязан к git-sha).
| Слой | Статус |
|---|---|
| Аналитический калькулятор `/analytics/recommend` (Tier 3 per-bucket эластичность, кадастр vs рынок) | ✅ |
| DOM.РФ kn-API скрейпер (442 строящихся ЖК Свердл, sale_graph + infra + photos) | ✅ Celery beat + admin UI |
| NSPD geo bulk-fetcher (rosreestr2coord lite, без Playwright) | ✅ admin UI с per-target логами |
| Rosreestr CSV-сделки 2024Q1—2026Q1 (9 квартирных партиций, 7M строк) | ✅ |
| NSPD кадастровые кварталы + здания (709 cad-кварталов, 10 590 cad_buildings ЕКБ) | ✅ Celery beat + admin UI |
| OSM ekb_districts_geom (PostGIS-полигоны 8 районов ЕКБ) | ✅ |
| Objective ETL (Anton SQLite → PG, ports на psycopg v3) | ✅ admin UI |
| Obsidian Self-hosted LiveSync vault на `obsidian.gendsgn.ru` (268 entities из KG) | ✅ multi-device sync |
| Concept page (`/concept`) — Stage 1 Generative | 🟡 skeleton |
| Site Finder (`/site-finder`) — Stage 2 | 🔴 заглушка |
**Backlog:** [GitHub Issues](https://github.com/lekss361/-gendesign/issues) (трекаемые задачи с PR-связью) + [Obsidian vault](https://obsidian.gendsgn.ru) (планы, ADR, research — см. ниже про разделение).
---
## Quick start (локально)
**Требования:** Docker Desktop, Node.js 20+, [uv](https://docs.astral.sh/uv/) для backend dev.
```bash
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
docker compose up -d --build
curl http://localhost:8000/health # → {"status":"ok","environment":"dev"}
# Frontend: http://localhost:3000
# Swagger: http://localhost:8000/docs
```
Полезные `make`-таргеты: `logs`, `backend-shell`, `migrate`, `test`, `lint`, `typecheck`, `codegen` (TS-типы из OpenAPI).
---
## Архитектура
**Backend:** Python 3.12, FastAPI, SQLAlchemy 2.0, GeoAlchemy2, Pydantic v2, Celery + Redis, httpx, Shapely 2, scikit-learn.
**БД:** PostgreSQL 16 + PostGIS 3.4 (партиционированные `rosreestr_deals`, GIST на geom-полях, ~50 предметных таблиц).
**Frontend:** Next.js 15, React 19, TypeScript 5, Tailwind 4, TanStack Query, Leaflet/Mapbox, ECharts.
**Экспорт:** WeasyPrint (PDF), ezdxf (DXF), openpyxl (Excel).
**Dev:** uv lockfile, ruff, mypy strict (на `core` + `generative`), pytest, pre-commit hooks.
Структура монорепо:
```
backend/ FastAPI app, services (analytics_queries, scrapers, generative, site_finder), workers (Celery)
frontend/ Next.js app router (analytics, admin, concept, site-finder)
data/sql/ ETL артефакты — миграции схемы, загрузчики rosreestr/anton/nspd
ops/ backup.sh + deploy скрипты
scripts/ утилиты (migrate_kg_to_obsidian.py, setup-couchdb.sh, cleanup_ghosts.py)
docs/ стратегические снапшоты (актуальное knowledge — в Obsidian vault)
memory/ legacy JSONL knowledge graph (deprecated, не обновляется — данные в Obsidian)
docker-compose.prod.yml main стек (backend, frontend, postgres, redis, worker, beat, caddy)
docker-compose.obsidian.yml obsidian-стек (CouchDB) — деплоится отдельно
.github/workflows/
├── deploy.yml main → пересборка backend/frontend образов + SSH deploy
└── deploy-obsidian.yml obsidian-стек (CouchDB compose changes + bootstrap)
```
---
## Аналитика — что доступно
В прод-БД ~50 предметных таблиц:
- **`domrf_kn_*`** — DOM.РФ объекты, квартиры, sale_graph, infrastructure, photos (1500+ ЖК Свердл).
- **`rosreestr_deals`** — партиционированные ДДУ/ДКП-сделки 2024Q1—2026Q1, ~7M строк, 27 мес истории.
- **`cad_quarters_geom` + `cad_buildings`** — NSPD кадастровые кварталы и здания (cost_value, year_built, floors, geom).
- **`ekb_districts_geom`** — PostGIS-полигоны OSM для spatial-join.
- **`cbr_mortgage_series`, `yandex_realty_zk`, `domrf_realization`, `sber_ddf_metrics`** — макро/cross-validation.
**Калькулятор `/analytics/recommend`** считает квартирографию (5 size-бакетов) с per-bucket эластичностью через регрессию sale_graph, нормировкой на район/класс/конкурентов, кадастр-vs-рынок cross-check, и инверсным режимом «требуемая цена для срока X мес».
Подробное описание схемы БД, helper-views, FK и 27.04 history — в Obsidian vault: `domains/analytics/Analytics_Dashboard_Apr27`, `domains/domrf/events/DomRF_Lazy_Loaded_Apr27_2026`, `events/Anton_Imported_Apr27_2026`, `domains/cadastre/Cad_Quarter_Backfill_Apr30`. См. также `data/sql/*.sql` (DDL артефакты).
---
## Production хостинг
**Beget Cloud, Москва, 2 vCPU / 4 GB / 40 GB NVMe.** Стоимость ~1 140 ₽/мес сервер + ~17 ₽/мес домен.
**Два изолированных стека через docker compose, общая Docker network `gendesign_shared`:**
1. **Main стек** (`docker-compose.prod.yml`, project `gendesign`):
`postgres` + `redis` + `backend` (FastAPI) + `worker` + `beat` (Celery, Chromium только в worker) + `frontend` + `caddy` (auto-TLS Let's Encrypt). Backend/frontend bind на `127.0.0.1` — наружу только Caddy.
2. **Obsidian стек** (`docker-compose.obsidian.yml`, project `gendesign-obsidian`):
`couchdb:3` — Self-hosted LiveSync remote для multi-device sync vault'а на `obsidian.gendsgn.ru`. Caddy в main-стеке маршрутизирует через `gendesign_shared` network.
**Split deploy** — изменения в main НЕ перезагружают obsidian (и наоборот). Каждый стек со своим workflow.
**SSH-only по ключу к non-root пользователю `gendesign`**, fail2ban активен. UFW: 22/80/443.
**GitHub Actions deploys:**
- [`.github/workflows/deploy.yml`](.github/workflows/deploy.yml) — main: триггер на `backend/**`, `frontend/**`, `Caddyfile`, `docker-compose.prod.yml`. Build backend lean + worker-with-chromium + frontend → push в приватный GHCR → SSH `git reset --hard`, sed `SENTRY_RELEASE=$IMAGE_TAG` в `backend/.env.runtime`, `compose pull && up -d`, `caddy reload`, `curl /health`.
- [`.github/workflows/deploy-obsidian.yml`](.github/workflows/deploy-obsidian.yml) — obsidian: триггер на `docker-compose.obsidian.yml`, `scripts/setup-couchdb.sh`, `docs/obsidian-livesync.md`. Без сборки образов (couchdb:3 с DockerHub), SSH `compose up -d` + idempotent bootstrap (CORS, DB, лимиты).
**GitHub Secrets:** `DEPLOY_HOST`, `DEPLOY_USER`, `DEPLOY_SSH_KEY`, `DEPLOY_PORT`. Сервер авторизуется в GHCR однократно через PAT с `read:packages`. `COUCHDB_USER`/`COUCHDB_PASSWORD` — в `backend/.env.runtime` на VPS (не в репе).
**Триггеры миграции на Yandex Cloud:** 3-й платящий пилот / Раунд А / госзаказ (нужен реестр ПО) / БД >10 GB / >50 RPS. На YC ~1015 тыс ₽/мес.
### Операционные грабли
- `docker compose restart` НЕ перечитывает `env_file:` — после правки `.env` всегда `up -d --force-recreate --no-deps backend`.
- `deploy.yml` использует `git reset --hard origin/main` — ручные правки в `/opt/gendesign` будут стёрты при следующем деплое (`.env`-файлы переживут — в `.gitignore`).
- На проде всегда указывать `-f docker-compose.prod.yml` (без него поднимет dev compose без Caddy).
- `caddy reload` не сбрасывает retry-queue для ACME. При смене hostname с битым cert-state: `docker volume rm gendesign_caddy_data && up -d caddy`.
---
## Roadmap (12 недель)
| Stage | Сроки | Что | Acceptance |
|---|---|---|---|
| **0** ✅ | нед. 1 | Скелет монорепо, CI, прод | curl /health = ok |
| **Sprint 1** ✅ | конец апр 2026 | NSPD-скрейпер + per-bucket эластичность + кадастр cross-check + Sentry release tracking | recommend_mix Tier 3 в проде |
| **1a** | нед. 23 | Shapely-сервис, отступы, API-контракт `/concept` ([#5](https://github.com/lekss361/-gendesign/issues/5)) | GeoJSON → 3 заглушки |
| **1b** | нед. 45 | Greedy-алгоритм, 3 стратегии, STRtree ([#12](https://github.com/lekss361/-gendesign/issues/12)) | 3 варианта ≤15с на 1 га |
| **1c** | нед. 67 | ТЭП + финмодель + PDF/Excel/DXF ([#6](https://github.com/lekss361/-gendesign/issues/6)) | Продаваемый артефакт |
| **2a** | нед. 89 | ПКК-парсер + sales_tracker ([#7](https://github.com/lekss361/-gendesign/issues/7)) | ≥1000 участков ЕКБ |
| **2b** | нед. 1011 | Скоринг + API + UI Site Finder ([#8](https://github.com/lekss361/-gendesign/issues/8)) | Карта с цветовой градацией |
| **2c** | нед. 12 | Site Finder ↔ Generative + реестр ПО ([#9](https://github.com/lekss361/-gendesign/issues/9)) | 3 платящих пилота |
Аналитический backlog: [#17](https://github.com/lekss361/-gendesign/issues/17) velocity-anomaly, [#18](https://github.com/lekss361/-gendesign/issues/18) ekb_districts median refresh, [#19](https://github.com/lekss361/-gendesign/issues/19) competitor-360, [#20](https://github.com/lekss361/-gendesign/issues/20) mortgage-rate sensitivity, [#21](https://github.com/lekss361/-gendesign/issues/21) cad_buildings filters в Site Finder.
---
## Команда и память проекта
**2 фуллстек-разработчика, part-time 20 ч/нед**, ритм: 1 синк/нед, daily-async в Telegram, PR-review обязательный, trunk-based. Codegen TS-типов из Pydantic — `npm run codegen`.
### Knowledge base — Obsidian vault
**Источник правды** — Obsidian vault на `obsidian.gendsgn.ru` (Self-hosted LiveSync + CouchDB). Markdown-файлы с `[[wiki-links]]`, MOC-страницами, Graph View и тегами. Multi-device sync: desktop / laptop / iPhone / Android. **268 entities** мигрированы из исторического JSONL knowledge graph (`scripts/migrate_kg_to_obsidian.py`), который теперь deprecated.
Структура vault:
- `meta/` — гайды, credentials, project meta (Project_GenDesign, TechStack, NorthStar)
- `domains/{domrf,cadastre,rosreestr,analytics,ui,api,geo,infra}/` — knowledge по бизнес-доменам
- `code/{modules,schemas,patterns,hooks,tasks}/` — code-level entities
- `decisions/` — ADR / планы / политики
- `fixes/` — bug-журналы
- `sessions/`, `sprints/`, `events/` — chronological logs
- `research/`, `sources/`, `feedback/`, `github/`, `limitations/` — прочее
- `old/` — архив legacy paths (redirect-stubs)
**Подключение коллеги** — гайды в самом vault'е:
- `meta/01_connect_devices.md` — установка Obsidian + LiveSync на любую платформу (через Setup URI или 4 поля)
- `meta/03_obsidian_plugins.md` — какие плагины ставить (Local REST API, Templater, Dataview)
- `meta/04_mcp_obsidian_setup.md` — подключение Claude к vault через MCP
**Legacy:** старый knowledge graph JSONL (`memory/memory-gendesign.jsonl`) — снапшот на момент 2026-05-11, не обновляется. Все новые факты пишутся в Obsidian.
### Где вести задачи — GitHub Issues vs Obsidian
Используем **оба**, но с чёткой ролью:
| | GitHub Issues | Obsidian vault |
|---|---|---|
| Что сюда | Bug + Feature + Refactor — всё с **связью с кодом / PR** | Knowledge: research, ADR, planning, draft-ideas |
| Lifecycle | Open → Assigned → PR → Merged → Closed | Append-only журнал решений и контекста |
| Уведомления | GitHub email/mobile + integrations | Никаких (читаешь когда сам пришёл) |
| Поиск | GitHub search + labels + milestones | BM25 + tags + Graph + MOC |
| Видимость | Команде в reviewer'ах | Всем у кого есть vault password |
| Сроки | Milestones (12-week roadmap) | Frontmatter `date:`, `status:`, `due:` |
**Правило перехода:** Obsidian `fixes/Bug_X.md` со `status: OPEN` → когда требует PR — создаём **GitHub Issue**, ссылку прописываем во frontmatter `.md` (`github_issue: 42`). Bug-исследование живёт в vault'е, action item — в Issues.
**Что куда:**
- `Bug_*` (vault) + GitHub Issue с тегом `bug` → обнаружен баг, фикс через PR
- `decisions/*` (vault) — ADR, не нужен GitHub Issue
- `research/*` (vault) — анализ источников, конкуренты, метрики
- `sessions/*` (vault) — журналы рабочих сессий
- GitHub Issues `feat/*` — фичи + PR на 1+ files, видимые в milestones
---
## Полезные ссылки
| | |
|---|---|
| 🌐 Production | https://gendsgn.ru/ |
| 🩺 Health | https://gendsgn.ru/health |
| 📚 OpenAPI | https://gendsgn.ru/openapi.json · [Swagger UI](https://gendsgn.ru/docs) |
| 🗂 Knowledge vault | https://obsidian.gendsgn.ru (требуется Obsidian + Self-hosted LiveSync, см. vault `meta/01_connect_devices.md`) |
| Backlog | [Issues](https://github.com/lekss361/-gendesign/issues) · [Milestones](https://github.com/lekss361/-gendesign/milestones) |
| Деплой | [GitHub Actions](https://github.com/lekss361/-gendesign/actions) · [GHCR пакеты](https://github.com/lekss361?tab=packages) |
| Мониторинг | [Sentry](https://qqq-5y.sentry.io/insights/projects/gendesign-backend/) |
| Инфра | Beget VPS [`cp.beget.com/cloud/...`](https://cp.beget.com/cloud/servers/jolly-yakov-3) · [DNS](https://cp.beget.com/dns/14193206) |
**Стратегические документы (снимки):** [`docs/MVP_Goals_Python.md`](docs/MVP_Goals_Python.md), [`docs/Бизнес-план v2.1 - Site Finder + Roadmap 12 месяцев.md`](docs/), [`docs/obsidian-livesync.md`](docs/obsidian-livesync.md). При расхождении с vault'ом — доверяем vault'у.