# Generative Design + Site Finder Две продуктовые линии в одной воронке: **Site Finder** (AI-подбор инвестиционных земельных участков) + **Generative Design** (автоматическая генерация концепций застройки) для девелоперов РФ. Целевой регион Discovery — Свердловская обл. (ЕКБ, ПЗЗ, МСК-66). ## North Star К концу месяца 3: **3 платящих пилота** (≥30 тыс. ₽/мес каждый) + заявка в реестр российского ПО → право на Раунд А (20–25 млн ₽). --- ## Текущий статус (июнь 2026) **Live:** [https://gendsgn.ru/](https://gendsgn.ru/) — HTTP/2+HTTP/3, валидный TLS, [/health](https://gendsgn.ru/health) `{"status":"ok"}`. Полный CI/CD: **Forgejo Actions** ([git.gendsgn.ru](https://git.gendsgn.ru)) → GHCR → SSH-deploy на Beget VPS (миграция с GitHub Actions 16 мая 2026). Sentry/GlitchTip активен (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:** [Forgejo Issues](https://git.gendsgn.ru/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) — деплоится отдельно .forgejo/workflows/ (Forgejo Actions — основной CI/CD после миграции 16.05.2026) ├── ci.yml lint (ruff) + mypy + pytest на PR ├── deploy.yml main → пересборка backend/frontend образов + auto-apply data/sql/*.sql + SSH deploy ├── deploy-tradein.yml tradein-mvp стек (отдельный пайплайн) └── stale-claims.yml авто-снятие протухших claim-меток в bot-пайплайне .github/workflows/ (остаточные — только obsidian-стек на GitHub) └── 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. **Forgejo Actions deploys** (self-hosted `git.gendsgn.ru`, мигрировано с GitHub Actions 16.05.2026): - [`.forgejo/workflows/ci.yml`](.forgejo/workflows/ci.yml) — на PR: ruff lint + mypy (selective strict) + pytest. Блокирует merge при провале. - [`.forgejo/workflows/deploy.yml`](.forgejo/workflows/deploy.yml) — main: триггер на `backend/**`, `frontend/**`, `Caddyfile`, `docker-compose.prod.yml`, `data/sql/**`. Build backend lean + worker-with-chromium + frontend → push в приватный GHCR → SSH `git reset --hard`, **auto-apply pending `data/sql/NN_*.sql` через `_schema_migrations`** (idempotent, см. ниже про миграции), sed `SENTRY_RELEASE=$IMAGE_TAG` в `backend/.env.runtime`, `compose pull && up -d`, `caddy reload`, `curl /health`. - [`.forgejo/workflows/deploy-tradein.yml`](.forgejo/workflows/deploy-tradein.yml) — tradein-mvp стек (отдельный пайплайн). - [`.github/workflows/deploy-obsidian.yml`](.github/workflows/deploy-obsidian.yml) — obsidian (**остался на GitHub**): триггер на `docker-compose.obsidian.yml`, `scripts/setup-couchdb.sh`, `docs/obsidian-livesync.md`. Без сборки образов (couchdb:3 с DockerHub), SSH `compose up -d` + idempotent bootstrap (CORS, DB, лимиты). **Forgejo Secrets / Variables:** `DEPLOY_HOST`, `DEPLOY_USER`, `DEPLOY_SSH_KEY`, `DEPLOY_PORT`. Сервер авторизуется в GHCR однократно через PAT с `read:packages`. `COUCHDB_USER`/`COUCHDB_PASSWORD` — в `backend/.env.runtime` на VPS (не в репе). ### Миграции БД — `_schema_migrations`, не Alembic Схема развивается через **идемпотентные `data/sql/NN_*.sql`** (`CREATE … IF NOT EXISTS`, guarded `DO`-блоки). `deploy.yml` перед `compose up` прогоняет файлы в лексикографическом порядке, отмечая применённые в таблице-трекере `_schema_migrations` (применяется ровно один раз каждый). Каталог `backend/alembic/versions/` **пуст** — Alembic в проде не используется. Подробности и граница «raw SQL vs ORM» — [`docs/Schema_Migrations_vs_Alembic.md`](docs/Schema_Migrations_vs_Alembic.md). **Триггеры миграции на Yandex Cloud:** 3-й платящий пилот / Раунд А / госзаказ (нужен реестр ПО) / БД >10 GB / >50 RPS. На YC ~10–15 тыс ₽/мес. ### Операционные грабли - `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** | нед. 2–3 | Shapely-сервис, отступы, API-контракт `/concept` ([#5](https://git.gendsgn.ru/lekss361/gendesign/issues/5)) | GeoJSON → 3 заглушки | | **1b** | нед. 4–5 | Greedy-алгоритм, 3 стратегии, STRtree ([#12](https://git.gendsgn.ru/lekss361/gendesign/issues/12)) | 3 варианта ≤15с на 1 га | | **1c** | нед. 6–7 | ТЭП + финмодель + PDF/Excel/DXF ([#6](https://git.gendsgn.ru/lekss361/gendesign/issues/6)) | Продаваемый артефакт | | **2a** | нед. 8–9 | ПКК-парсер + sales_tracker ([#7](https://git.gendsgn.ru/lekss361/gendesign/issues/7)) | ≥1000 участков ЕКБ | | **2b** | нед. 10–11 | Скоринг + API + UI Site Finder ([#8](https://git.gendsgn.ru/lekss361/gendesign/issues/8)) | Карта с цветовой градацией | | **2c** | нед. 12 | Site Finder ↔ Generative + реестр ПО ([#9](https://git.gendsgn.ru/lekss361/gendesign/issues/9)) | 3 платящих пилота | Аналитический backlog: [#17](https://git.gendsgn.ru/lekss361/gendesign/issues/17) velocity-anomaly, [#18](https://git.gendsgn.ru/lekss361/gendesign/issues/18) ekb_districts median refresh, [#19](https://git.gendsgn.ru/lekss361/gendesign/issues/19) competitor-360, [#20](https://git.gendsgn.ru/lekss361/gendesign/issues/20) mortgage-rate sensitivity, [#21](https://git.gendsgn.ru/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. ### Где вести задачи — Forgejo Issues vs Obsidian Используем **оба**, но с чёткой ролью (трекер мигрирован с GitHub на self-hosted Forgejo 16.05.2026): | | Forgejo Issues ([git.gendsgn.ru](https://git.gendsgn.ru/lekss361/gendesign/issues)) | Obsidian vault | |---|---|---| | Что сюда | Bug + Feature + Refactor — всё с **связью с кодом / PR** | Knowledge: research, ADR, planning, draft-ideas | | Lifecycle | Open → Assigned → PR → Merged → Closed | Append-only журнал решений и контекста | | Уведомления | Forgejo email/webhook | Никаких (читаешь когда сам пришёл) | | Поиск | Forgejo 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 — создаём **Forgejo Issue**, ссылку прописываем во frontmatter `.md` (`issue: 42`). Bug-исследование живёт в vault'е, action item — в Issues. **Что куда:** - `Bug_*` (vault) + Forgejo Issue с тегом `bug` → обнаружен баг, фикс через PR - `decisions/*` (vault) — ADR, не нужен Issue - `research/*` (vault) — анализ источников, конкуренты, метрики - `sessions/*` (vault) — журналы рабочих сессий - Forgejo Issues `feat/*` — фичи + PR на 1+ files, видимые в milestones ### Claude Code subagents (`.claude/agents/`) Разработка ведётся через Claude Code с **6 кастомными subagent'ами** (path-scoped, со своими MCP-«учётками»: прод-PostgreSQL, Obsidian vault, Forgejo, GlitchTip). Полные правила — `.claude/rules/` + корневой [`CLAUDE.md`](CLAUDE.md). | Agent | Scope / зона ответственности | |---|---| | `tech-analyst` | Нечёткая / cross-domain задача → план перед кодом | | `backend-engineer` | `backend/app/**` — FastAPI, Celery, scrapers, services | | `frontend-engineer` | `frontend/src/**` — Next.js 15, React 19, hooks | | `database-expert` | `data/sql/**.sql`, схема, EXPLAIN ANALYZE, прод-БД через MCP | | `devops-engineer` | `docker-compose*.yml`, `Caddyfile`, `.forgejo/workflows/**` | | `code-reviewer` | Pre-push lint: security, correctness, conventions | **Workflow:** тривиально (typo, 1-line) → main session; single-domain → профильный worker; cross-domain → `tech-analyst` сначала. Worker → `code-reviewer` → коммит → push → PR в Forgejo. Branch + PR обязательны, никаких direct push в main. --- ## Полезные ссылки | | | |---|---| | 🌐 Production | https://gendsgn.ru/ | | 🩺 Health | https://gendsgn.ru/health | | 📚 OpenAPI | [Swagger UI](https://gendsgn.ru/docs) · https://gendsgn.ru/openapi.json (за Caddy basic_auth) | | 🗂 Knowledge vault | https://obsidian.gendsgn.ru (требуется Obsidian + Self-hosted LiveSync, см. vault `meta/01_connect_devices.md`) | | 🧰 Git / CI | [git.gendsgn.ru](https://git.gendsgn.ru/lekss361/gendesign) (Forgejo) · [`CLAUDE.md`](CLAUDE.md) — правила разработки | | Backlog | [Issues](https://git.gendsgn.ru/lekss361/gendesign/issues) · [Milestones](https://git.gendsgn.ru/lekss361/gendesign/milestones) | | Деплой | [Forgejo Actions](https://git.gendsgn.ru/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'у.