GenDesign — full migration from GitHub including issues/PR/wiki (2026-05-16)
Find a file
lekss361 59f222eaf3
feat(db): bulk cadastre schema — 7 tables + cadastre_jobs (#168 PR1/5) (#169)
* feat(db): schema migration for bulk cadastre ingest layers (#168)

Add 7 cadastre layer tables + cadastre_jobs saga-state table.

Tables:
- cad_parcels (36368 ЗУ ЕГРН) replaces cad_parcels_geom
- cad_buildings v2 wide schema (replaces existing, backed up as cad_buildings_old_apr26)
- cad_constructions (36383 Сооружения + ЕГРН, flag is_egrn)
- cad_oncs (36384), cad_enk (39663), cad_zouit (4 categoryIds), cad_quarter_stats
- cadastre_jobs (resumable saga state, mirrors geo_jobs pattern)

GIST + BTREE indexes. Migration of cad_parcels_geom data via INSERT...SELECT.
Restore v_complex_full + v_complex_buildings views after table rename.

* fixup(db): address PR #169 bot review — 2 blockers + 3 lessers

Blocker #1: cad_parcels_geom DROP → back-compat VIEW
  Old DROP TABLE would break site-finder analyze fallback (per 83_*.sql COMMENT).
  Now: drop old BASE TABLE (guarded by table_type), create VIEW over cad_parcels
  with identical 4-column signature. Callers continue to work; PR2/5 will switch.

Blocker #2: K.3 redundant RENAME CONSTRAINT removed
  ALTER INDEX RENAME on PK index already renames the backing constraint in PG16.
  Second ALTER TABLE RENAME CONSTRAINT would throw 'does not exist' and abort tx.

Lesser #1: cadastre_jobs.status CHECK constraint
  Inline CHECK (status IN ('queued','running','done','failed','zombie','cancelled','paused'))
  per partial-index intent and admin UI plan.

Lesser #2: COMMENT ON TABLE for all 8 tables + view (keeps convention from 63, 83).

Lesser #3: set_updated_at() triggers on 7 tables with updated_at column.
  Reuses existing function (verified present). DO $$ guards on pg_trigger
  for idempotent re-apply. cadastre_jobs excluded (uses heartbeat_at instead).

---------

Co-authored-by: lekss361 <claudestars@proton.me>
2026-05-15 13:05:25 +03:00
.github/workflows fix(deploy): source root .env (где POSTGRES_USER) не backend/.env (#153) 2026-05-15 08:19:17 +03:00
backend feat(cadastre): NSPDBulkClient + schemas for bulk ingest (#168 PR2/5) (#170) 2026-05-15 12:50:41 +03:00
data feat(db): bulk cadastre schema — 7 tables + cadastre_jobs (#168 PR1/5) (#169) 2026-05-15 13:05:25 +03:00
docs feat(deploy): split obsidian stack from main + path-filtered GHA 2026-05-11 09:51:31 +03:00
frontend fix(site-finder): visible by-quarter pipeline bars (#167) 2026-05-15 10:35:51 +03:00
memory Memory: +rel Project_GenDesign→SiteFinder_v0_2_May08 (deploys), SiteFinder_v0_2_May08→MVP_Scope_AreaSelect_Apr25 (contradicts... (2026-05-10 22:44:45 +05) 2026-05-10 22:44:45 +05:00
ops ops: alembic baseline, pre-commit, TIGER cleanup, pg_dump scripts 2026-04-26 13:08:51 +03:00
scripts feat(infra): auto-apply data/sql/*.sql migrations in deploy pipeline (#150) (#151) 2026-05-15 08:06:54 +03:00
site-finder Import Site Finder app from analysis/ vibe-coding session 2026-05-10 22:42:25 +05:00
.editorconfig init 2026-04-25 13:45:19 +03:00
.env.example Fix env defaults: use Docker network hostnames + parametrize compose 2026-04-25 19:36:10 +03:00
.gitignore feat(objective): full sync pipeline + dynamic admin config 2026-05-10 19:54:15 +03:00
.pre-commit-config.yaml ops: alembic baseline, pre-commit, TIGER cleanup, pg_dump scripts 2026-04-26 13:08:51 +03:00
Caddyfile feat(deploy): split obsidian stack from main + path-filtered GHA 2026-05-11 09:51:31 +03:00
CLAUDE.md feat(infra): auto-apply data/sql/*.sql migrations in deploy pipeline (#150) (#151) 2026-05-15 08:06:54 +03:00
debug.log refactor(nspd-geo): unify on rosreestr2coord v5, drop legacy column 2026-05-11 14:13:33 +03:00
docker-compose.obsidian.yml fix 2026-05-11 09:57:40 +03:00
docker-compose.prod.yml chore(infra): correct frontend healthcheck + tighten depends_on (re-apply #117) (#120) 2026-05-14 23:24:47 +03:00
docker-compose.yml ship #13-16: multi-target Dockerfile, per-object drill-in, CRM pipeline, 2026-04-27 19:32:37 +03:00
Makefile ops: alembic baseline, pre-commit, TIGER cleanup, pg_dump scripts 2026-04-26 13:08:51 +03:00
README.md upd readme 2026-05-11 13:43:15 +03:00
sshkey.txt fix(worker): port objective_etl from psycopg2 → psycopg v3 2026-05-11 12:07:57 +03:00

Generative Design + Site Finder

Две продуктовые линии в одной воронке: Site Finder (AI-подбор инвестиционных земельных участков) + Generative Design (автоматическая генерация концепций застройки) для девелоперов РФ. Целевой регион Discovery — Свердловская обл. (ЕКБ, ПЗЗ, МСК-66).

North Star

К концу месяца 3: 3 платящих пилота (≥30 тыс. ₽/мес каждый) + заявка в реестр российского ПО → право на Раунд А (2025 млн ₽).


Текущий статус (май 2026)

Live: https://gendsgn.ru/ — HTTP/2+HTTP/3, валидный TLS, /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 (трекаемые задачи с PR-связью) + Obsidian vault (планы, ADR, research — см. ниже про разделение).


Quick start (локально)

Требования: Docker Desktop, Node.js 20+, uv для backend dev.

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 — 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 — 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) GeoJSON → 3 заглушки
1b нед. 45 Greedy-алгоритм, 3 стратегии, STRtree (#12) 3 варианта ≤15с на 1 га
1c нед. 67 ТЭП + финмодель + PDF/Excel/DXF (#6) Продаваемый артефакт
2a нед. 89 ПКК-парсер + sales_tracker (#7) ≥1000 участков ЕКБ
2b нед. 1011 Скоринг + API + UI Site Finder (#8) Карта с цветовой градацией
2c нед. 12 Site Finder ↔ Generative + реестр ПО (#9) 3 платящих пилота

Аналитический backlog: #17 velocity-anomaly, #18 ekb_districts median refresh, #19 competitor-360, #20 mortgage-rate sensitivity, #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
🗂 Knowledge vault https://obsidian.gendsgn.ru (требуется Obsidian + Self-hosted LiveSync, см. vault meta/01_connect_devices.md)
Backlog Issues · Milestones
Деплой GitHub Actions · GHCR пакеты
Мониторинг Sentry
Инфра Beget VPS cp.beget.com/cloud/... · DNS

Стратегические документы (снимки): docs/MVP_Goals_Python.md, docs/Бизнес-план v2.1 - Site Finder + Roadmap 12 месяцев.md, docs/obsidian-livesync.md. При расхождении с vault'ом — доверяем vault'у.