GenDesign — full migration from GitHub including issues/PR/wiki (2026-05-16)
Find a file
lekss361 81cf274e80 fix(#234): address re-review nits — Settings singleton + docstring sync
1. _acquire_harvest_lock: Settings() instance → singleton 'settings' import
   from app.core.config — соответствует convention (scrape_kn.py, objective.py,
   celery_app.py все используют singleton).
2. _trigger_harvest docstring: убрана incorrect фраза «остальные ... видят
   harvest_eta_seconds от первого запроса» (код возвращает eta=None для
   denied-lock callers). Заменена на actual behavior: graceful no-data UI
   с ПКК fallback на FE.

PR #250 re-review followup (issues #3 + docstring sync).
2026-05-17 09:31:43 +03:00
.claude refactor(claude): split 700-line CLAUDE.md into path-scoped .claude/rules/ (#188) 2026-05-15 23:06:33 +03:00
.forgejo/workflows fix(infra): wire GlitchTip DSNs (build-arg + env_file) + reject sentry.io promote 2026-05-16 21:48:28 +03:00
.github/workflows chore(ci): run CI on push to feature branches (#195) 2026-05-16 08:26:04 +00:00
backend fix(#234): address re-review nits — Settings singleton + docstring sync 2026-05-17 09:31:43 +03:00
data feat(#114): seed 3 default weight presets + include_system API param 2026-05-16 22:49:56 +03:00
docs feat(deploy): split obsidian stack from main + path-filtered GHA 2026-05-11 09:51:31 +03:00
frontend fix(#234): NSPD harvest ETA badge + SETNX dedupe (Sub-PR C) 2026-05-17 09:13:06 +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 fix(infra): bootstrap_glitchtip — \gexec instead of DO block (psql var trap) (#219) 2026-05-16 15:54:29 +00: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 feat(infra): GlitchTip self-hosted error tracking (#204 devops) (#205) 2026-05-16 15:08:50 +00:00
.gitignore feat(frontend): @sentry/nextjs init для GlitchTip (#204 frontend) (#208) 2026-05-16 15:09:38 +00:00
.pre-commit-config.yaml ops: alembic baseline, pre-commit, TIGER cleanup, pg_dump scripts 2026-04-26 13:08:51 +03:00
Caddyfile fix(infra): restore git.gendsgn.ru block in Caddyfile 2026-05-16 19:51:54 +03:00
CLAUDE.md refactor(claude): split 700-line CLAUDE.md into path-scoped .claude/rules/ (#188) 2026-05-15 23:06:33 +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 fix(beat): use /tmp/celerybeat-schedule (workdir /app not writable by app user) 2026-05-16 22:03:45 +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'у.