gendesign/memory/memory-gendesign.jsonl

917 lines
No EOL
500 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

{"type":"_aim","source":"mcp-knowledge-graph"}
{"type":"entity","name":"Project_GenDesign","entityType":"project","observations":["Стартап: AI-подбор земельных участков (Site Finder) + автоматическая генерация концепций застройки (Generative Design) для девелоперов РФ","Two-in-one воронка: от инвест-критериев → найденный участок → концепт застройки → финансовая модель","Конкуренты: rTIM (только концепт-стадия, нет site-selection), TestFit (нет РФ-данных)","Целевая аудитория: инвестдепартаменты + архитектурно-проектные отделы региональных девелоперов","Фаза 0 — Discovery MVP, апрель–июнь 2026 (3 месяца)","Бюджет Фазы 0: 0,91,2 млн ₽","Корневой репозиторий: C:\\Users\\user\\source\\repos\\gendesign","Документы хранятся в docs/ внутри репозитория"]}
{"type":"entity","name":"TechStack_v2.2","entityType":"tech_stack","observations":["Решение зафиксировано в апреле 2026: переход с .NET на Python для Discovery MVP","Backend: Python 3.12, FastAPI 0.115+, SQLAlchemy 2.0, GeoAlchemy2, Pydantic v2, Alembic, Celery + Redis, httpx","Геометрия: Shapely 2.0, GeoPandas 1.0, Pyproj (проекции WGS84 ↔ UTM ↔ МСК-66 для Свердловской обл.), Rasterio","ML: XGBoost (скоринг участков), scikit-learn, pandas, NumPy","База данных: PostgreSQL 16 + PostGIS 3.4, Redis 7","Frontend: Next.js 15, React 19, TypeScript 5, Tailwind CSS 4, shadcn/ui, TanStack Query, Mapbox GL JS или Leaflet","Экспорт: WeasyPrint (PDF), ezdxf (DXF), openpyxl (Excel)","Инфра: Yandex Cloud или VK Cloud, Docker, GitHub Actions, Sentry","Dev tools: uv (зависимости), ruff (линтер+форматтер), mypy (типизация), pytest"]}
{"type":"entity","name":"NorthStar_DiscoveryMVP","entityType":"goal","observations":["К концу месяца 3 (июнь 2026): 3 платящих пилотных клиента, ≥30 тыс. ₽/мес каждый","Заявка в реестр российского ПО подана","Це́ль: получить право пройти в Раунд А на 2025 млн ₽","Acceptance criteria разбиты на 3 блока: функционально / бизнесово / технически","Правило перехода: 3/3 → Раунд А; 2/3 → продление Фазы 0 на 12 мес.; 1/3 или меньше → стоп проекта","В v2.2 цель = 3 пилота; в v2.1 (бизнес-план) указано 4 пилота — расхождение, требует синхронизации в пользу 3"]}
{"type":"entity","name":"Phase0_DiscoveryMVP","entityType":"phase","observations":["Discovery MVP, месяцы 13 после старта","Пилотный регион: Свердловская обл. (Екатеринбург, ПЗЗ Екатеринбурга, МСК-66)","Месяц 1 цели: ООО зарегистрировано, прототип Site Finder с 1000 участков, 50 целевых клиентов в CRM, 5 cold-outreach, 3 встречи","Месяц 2 цели: 15 встреч кумулятивно, 2 LOI, 1 платящий пилот (≥30 тыс. ₽/мес), демо на реальных участках, первая статья","Месяц 3 цели: 20+ встреч, 3 платящих пилота, 7+ LOI, 1 регадминистрация в переговорах, заявка в реестр ПО, инвест-deck (12 слайдов), финмодель на 5 лет"]}
{"type":"entity","name":"Validation_Findings_Apr25","entityType":"review","observations":["Дата валидации: 25 апреля 2026","КРИТИЧНО: бизнес-план v2.1 не синхронизирован со стеком v2.2 — в плане 12 мес. месяцы 14 ещё ссылаются на .NET Core 8","Несостыковка KPI: v2.1 = 4 платящих пилота, v2.2 = 3 — нужно остановиться на 3 (как в Acceptance Criteria v2.2)","Регион не зафиксирован однозначно: v2.1 пишет «Свердл. или Лен.», v2.2 — только Свердл. — закрепить Свердловскую","Прайсинг: пилот 30 тыс., прайс-лист 70120 тыс. — уточнить в финмодели для инвесторов: 70 тыс./мес как baseline","Технические риски: Time to First Value ≤10 мин амбициозно (предложение: 15 мин); генерация концепции ≤10 сек требует профилировки с первого билда","PostgreSQL TDE отсутствует в open-source — заменить на pgcrypto + шифрование чувствительных полей на уровне приложения","mypy --strict для всего MVP избыточен соло-разработчику — оставить только для core-модулей (geometry/scoring/financial)","99% uptime в рабочие часы для соло-разработчика рискованно — реалистично 95% + ответ в течение рабочего дня","Заявка в реестр ПО ≠ свидетельство; срок рассмотрения 60180 дней — учесть для расчёта Раунда А","Бюджет 1,2 млн ₽ + 3 мес. + один основатель плотный; рекомендация — заложить буфер +1 месяц или урезать DXF-экспорт из Discovery"]}
{"type":"entity","name":"Feedback_MemoryFirst","entityType":"feedback","observations":["Правило: вся информация по проекту gendesign хранится в memory-gendesign.jsonl (context=\"gendesign\"). Информация = факты, решения, результаты анализа, обсуждения стратегии, KPI, списки рисков, протоколы валидации и т.д.","НИКОГДА не создавать .md / .docx / .pdf / .pptx файлы самостоятельно — даже если кажется, что это поможет. Документы генерируются ТОЛЬКО по явному запросу («сделай md», «собери в документ», «выгрузи в docx»).","При поступлении новых фактов/решений в разговоре — сразу сохраняем в память через aim_memory_store / aim_memory_add_facts в context=\"gendesign\".","Для файловой генерации по запросу: запрос срез из памяти (aim_memory_search/read_all) → сборка документа. Память = единый источник правды, файлы = производные.","**Why:** пользователь хочет избежать разъехавшейся инфы между версиями доков (как случилось с v2.1/v2.2). Единый источник (граф памяти) — синхронен по определению.","**How to apply:** в любом обмене по этому проекту — (1) сначала читаем gendesign-память, (2) ведём диалог/анализ, (3) сохраняем новые выводы в память, (4) файлы только если пользователь явно запросил."]}
{"type":"entity","name":"Team_Setup","entityType":"team","observations":["2 фуллстек-разработчика (оба пишут Python + TypeScript)","Оба part-time по 20 ч/неделю — итого ~40 person-hours/неделю (эффективных с координацией ~33)","Разделение по фичам, а не по слоям — оба трогают backend и frontend","Ритм координации: 1 синк/неделю (30 мин), daily-async в Telegram, PR review обязательный","Ветвление: trunk-based, feature ветки ≤ 3 дней","Критичный тулинг: openapi-typescript для codegen TS-типов из Pydantic-схем (иначе два фуллстека плодят расхождения в API-контракте)"]}
{"type":"entity","name":"Stages_MVP_v1","entityType":"plan","observations":["Порядок: строго последовательный — Generative полностью, потом Site Finder","Общая оценка: 12 недель (Stage 0: 1 нед., Stage 1: 6 нед., Stage 2: 5 нед.)","Stage 0 (нед. 1) — скелет: монорепо backend+frontend, Docker с PostGIS+Redis, FastAPI hello, Next.js hello, openapi-typescript codegen, GitHub Actions CI, ruff+mypy(core)+pytest. Без JWT (single-tenant + X-Demo-User до Раунда А)","Stage 1a (нед. 2-3) — геометрия + API-контракт. A: Shapely-сервис (отступы, сетка), Pydantic ConceptInput/Output, POST /api/v1/concepts с заглушкой. B: страница /concept, Leaflet, импорт GeoJSON + отрисовка, форма параметров, вывод 3 вариантов в табах","Stage 1b (нед. 4-5) — алгоритм размещения. A: жадное заполнение, 3 стратегии, STRtree для коллизий, профилировка (цель ≤10с, fallback 15с). B: визуализация корпусов, метрики ТЭП, сравнение вариантов","Stage 1c (нед. 6-7) — ТЭП + финмодель + экспорты. A: teap.py, financial.py, openpyxl. B: WeasyPrint шаблон, ezdxf, UI кнопок скачивания","Acceptance Stage 1 (конец нед. 7): полигон→3 варианта→ТЭП+финмодель→PDF/Excel/DXF. Продаваемый артефакт для встреч с месяца 2","Stage 2a (нед. 8-9) — data pipeline. A: парсер ПКК Rosreestr (httpx async, retries), модель Parcel с GeoAlchemy2, загрузка 1000+ участков Екбурга. B: Overpass API для POI, ДОМ.РФ/ЦИАН для цен м², кеш в Redis","Stage 2b (нед. 10-11) — скоринг+API+UI. A: 3 критерия скоринга (эвристики, без XGBoost), POST /parcels/search. B: страница /site-finder, Mapbox, градация по рейтингу, фильтры, карточка","Stage 2c (нед. 12) — интеграция + полировка. Кнопка «Обсчитать концепцию», демо-наполнение 50 участков, бэкапы БД, подача в реестр ПО","Урезано из v2.2 из-за part-time ×2: XGBoost→Фаза 1, JWT-auth→перед Раундом А, mypy --strict только на core, время генерации ≤15с (а не 10с) как fallback"]}
{"type":"entity","name":"Hosting_Decision_Apr25","entityType":"decision","observations":["Дата: 25 апреля 2026","Выбор хостинга для РФ: рассматривались Yandex Cloud, VK Cloud, Selectel, Timeweb Cloud, Cloud.ru (Сбер)","Рекомендован Yandex Cloud как основной вариант для Discovery + Production","Обоснование: (1) лучшая поддержка PostGIS в Managed PostgreSQL в РФ; (2) Container Registry + Container Solution включены; (3) входит в реестр российского ПО — плюс к нашей заявке; (4) солидно выглядит для инвесторов Раунда А","Стоимость Discovery (~1015 тыс ₽/мес): VM Compute s3-c2-m4 (~3-4 тыс), Managed Postgres 1vCPU/4GB/30GB SSD (~5-7 тыс), Container Registry (бесплатно до 5GB), Object Storage для бэкапов (~500₽)","Альтернатива для жёсткой экономии: Selectel дешевле в 1.52 раза, но требует ручной PostGIS-рутины. Резерв на случай проблем с YC","Архитектура production: 1×VM с Docker Compose (backend + frontend + Caddy reverse proxy + auto-TLS) + Managed PostgreSQL (отдельный сервис) + Object Storage (бэкапы)","Образы: backend + frontend пушатся в Yandex Container Registry из GitHub Actions; на VM выполняется docker compose pull && up -d","GitHub Secrets для deploy: YC_SA_JSON_CREDENTIALS, YC_REGISTRY_ID, DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY, DEPLOY_PORT (опционально)","Caddy выбран вместо nginx: авто-TLS через Let's Encrypt без ручных certbot-рутин — дешевле по времени сопровождения для part-time команды","Домен: покупать в .ru зоне (REG.RU или РуЦентр), DNS на Yandex Cloud DNS или Cloudflare бесплатный","Production-путь на VM: /opt/gendesign/docker-compose.prod.yml + .env + Caddyfile"]}
{"type":"entity","name":"Onboarding_Colleague_KG","entityType":"procedure","observations":["MCP-сервер для памяти: npm-пакет mcp-knowledge-graph (запуск через npx -y)","Команда в claude_desktop_config.json: command=npx, args=['-y','mcp-knowledge-graph','--memory-path','<путь к папке с .jsonl файлами>']","Путь в рабочей среде основателя: C:\\mcp\\.aim","Стратегия разделённой памяти между коллегами: git синхронизация файла memory-gendesign.jsonl + хард-линк из репо в MCP-папку. Источник правды — репо","Конфликты в .jsonl обычно простые (файл построчный): решаются выбором \"оставить обе стороны\". rebase, не merge","Ритуал: git pull перед началом работы, git commit+push после изменений памяти","Полный текст процедуры выдан в чате 25 апреля 2026; при повторном запросе — восстановить из этой сущности"]}
{"type":"entity","name":"Hosting_Pricing_Apr25","entityType":"research","observations":["Дата проверки: 25 апреля 2026, фактические цены с сайтов провайдеров","Целевой конфиг: 2 vCPU / 4 GB RAM / 30-40 GB NVMe SSD + public IPv4. 60 GB избыточен для Discovery (реальное использование диска 12-15 GB: OS+Docker 5-7 GB + Postgres+PostGIS 0.5-1 GB + логи+бэкапы 1-2 GB + буфер 5 GB)","Selectel Standard Line 2/4 GB = 2308.86 ₽/мес (CPU+RAM only) + диск 30 GB Network SSD ~270 ₽ + public IP. Итого ~2700-3000 ₽/мес. Дороже конкурентов в 2-3 раза","Selectel Shared Line 2/4 GB с 10% vCPU = 1239 ₽/мес — дешевле, но CPU слишком слабый для Postgres+PostGIS под реальной нагрузкой","Timeweb Cloud MSK 50: 2 vCPU 3.3 GHz / 4 GB / 50 GB NVMe / 1 Гбит/с = 1062 ₽/мес со скидкой 10% при годовом контракте (или ~1180 ₽ без контракта). IPv4 включён. Реестр ПО № 15725","Beget VPS Standard 2 vCPU 3+ GHz / 4 GB / 40 GB NVMe = 33 ₽/день сервер + 5 ₽/день IPv4 = 38 ₽/день ≈ 1140 ₽/мес. Автобэкапы раз в несколько дней бесплатно. KVM. Реестр ПО № 16697","Beget VPS 2/2/30 = 27 ₽/день + 5 ₽ IP = 32 ₽/день ≈ 960 ₽/мес — ещё дешевле, но 2 GB RAM маловато для Postgres+PostGIS+Redis+backend+frontend+Caddy","Рекомендация Discovery: Beget VPS 2/4/40 NVMe + IP ≈ 1140 ₽/мес (самый дешевый реально рабочий конфиг) или Timeweb Cloud MSK 50 ≈ 1062 ₽/мес (лучше NVMe, больше диск)","Ранее в Hosting_Decision_Apr25 был предложен Yandex Cloud (~10-15 тыс ₽/мес с managed services). Это вариант для продакшена после Раунда А, не для Discovery","Для Discovery Beget выигрывает по цене и бесплатным бэкапам. Timeweb выигрывает по UI/UX панели и большему диску. Selectel оправдан только если планируется быстрый перевод на managed Postgres/K8s в их экосистеме"]}
{"type":"entity","name":"SSH_Setup_Apr25","entityType":"infrastructure","observations":["SSH-ключ для проекта: ed25519, без passphrase (для автодеплоя из GitHub Actions)","Локация: $HOME\\.ssh\\gendesign_deploy (приватный) + .pub (публичный)","Comment ключа: 'gendesign-deploy'","SSH config alias: 'Host gendesign' с IdentityFile ~/.ssh/gendesign_deploy — коннект командой 'ssh gendesign'","Публичный ключ вручную загружается в панель хостинг-провайдера при создании сервера","Приватный ключ позже пойдёт в GitHub Secret DEPLOY_SSH_KEY (для deploy.yml workflow)","Windows-специфика: icacls нужен для ограничения прав на приватный ключ, иначе OpenSSH ругается на 'UNPROTECTED PRIVATE KEY FILE'"]}
{"type":"entity","name":"WorkSplit_Generative_Stage1","entityType":"plan","observations":["Принцип разделения: вертикальные срезы по этапам пользовательского пути, не по слоям","Person A — 'Geometry → Variants' owner: Shapely-сервис, нормативные отступы, жадный алгоритм с 3 стратегиями, STRtree коллизии, профилировка. API endpoint POST /concepts, владелец схемы ConceptInput+buildings_geojson. Фронт: Leaflet, импорт/отрисовка полигона, форма параметров, рендеринг 3 вариантов на карте","Person B — 'Variants → Reports' owner: TEAP-сервис, финансовая модель, экспорты PDF/Excel/DXF (WeasyPrint+openpyxl+ezdxf). API endpoint /concepts/:id/export, владелец схем TEAP+FinancialModel. Фронт: таблицы ТЭП, форма финмодели, кнопки скачивания, сравнение вариантов","Точка стыка = Pydantic-контракт ConceptVariant в backend/app/schemas/concept.py. Договариваются в первый день Stage 1a, дальше оба работают с заглушками друг друга без блокировки","Точка стыка 2 — codegen TS-типов: при любой правке схемы оба запускают 'npm run codegen' локально","Календарь по неделям (Stage 1, нед.2-7): A движется по вектору схема→отступы→алгоритм→стратегии→тесты. B движется по вектору схема→TEAP→financial→Excel→DXF→PDF→тесты","Альтернативный расклад при асимметрии навыков: Алгоритмист (A) берёт все 4 backend-сервиса (geometry+TEAP+financial+exporters), фронт минимум. Продуктовик (B) берёт весь фронт + UI экспортов, backend минимум (тонкий export endpoint)","Анти-паттерны: разделение backend/frontend (блокирует второго), общие прямые пуши в main, молчаливые правки Pydantic без codegen, pair programming на каждой задаче (дорого для part-time ×2)"]}
{"type":"entity","name":"DataSources_Pricing_Apr25","entityType":"research","observations":["Дата: 25 апреля 2026","В РФ открытых данных по реальным сделкам (Росреестр) НЕТ — только агрегаты. Цены и площади из агрегаторов (ЦИАН/ДомКлик/Авито) — по объявлениям, не по сделкам","Открытые официальные источники (бесплатно, без юрриска): ДОМ.РФ (наш.дом.рф + api.dom.rf, реестр новостроек, площади в жк, колво квартир по комнатностям, класс жилья); Росстат (fedstat.ru, средние цены м² по регионам квартально); Минстрой (норматив цены м² для субсидий); Главгосэкспертиза НЦС (gge.ru, себестоимость м² строительства)","Скрейпинг агрегаторов (серая зона): ЦИАН (cianparser/cianscraper либы на GitHub, но Cloudflare и рейтлимит); Авито; ДомКлик; Яндекс.Недвижимость. Юридически — нарушение ТОС, но исков против мелких парсеров немного","Платные отраслевые: ЕРЗ.РФ Премиум (50-100тыс ₽/год, отраслевой стандарт); Knight Frank/NF Group/CBRE отчеты; PROEstate Analytics; СберИндекс (бесплатно)","Industry-standard unit-mix (из практики): Студии/1к/2к/3к/4+к по классам. Эконом: 15-20/35-40/25-30/10-15/0-5%. Комфорт: 8-12/25-30/30-35/20-25/5-10%. Бизнес: 5-10/18-22/30-35/25-30/10-15%. Премиум: 0-5/10-15/30/30-35/20-25%","Средние площади квартир м² (студия/1к/2к/3к): Эконом 22-28/33-38/50-58/70-80; Комфорт 26-30/38-44/58-66/80-92; Бизнес 30-35/45-55/70-85/100-125; Премиум 35-45/55-70/90-110/130-180. Нормативная нижняя граница — СП 54.13330.2016","Рекомендация для Discovery: Цены — Росстат baseline + ручной парсинг/скрейп ЦИАН 200 объявлений по районам Екбурга. Площади+unit-mix — захардкодить таблицу с возможностью ручной правки. Себестоимость — НЦС Главгосэкспертизы. Новостройки-конкуренты — API ДОМ.РФ","Для реестра ПО декларируем только легальные источники: ДОМ.РФ, Росстат, Главгосэкспертиза, OpenStreetMap. Скрейп ЦИАН — «внутренний справочник curating». Для инвесторов Раунда А — «договорённости с источниками рыночных данных в проработке»"]}
{"type":"entity","name":"SalesTracking_Strategy_Apr25","entityType":"strategy","observations":["Дата анализа: 25 апреля 2026","Исходный вопрос: можно ли косвенно понять, какие квартиры продаются и какие нет. Ответ: да, через ejednevnyy мониторинг шахматок застройщиков + delta-tracking","Прямые данные о сделках в РФ закрыты: Росреестр ДДУ не в open data, нотариусы и банки — закрытые источники","Косвенные источники по точности: 1) Шахматки застройщиков — 95%+ точность, золотая жила. 2) ДОМ.РФ реестр ДДУ по ЖК — 100% на уровне агрегата. 3) Delta-tracking listings ЦИАН/Авито — 70% точность. 4) ДомКлик ипотечная статистика — sanity check на уровне района. 5) Фиксация снижений цен — сигнал «не продаётся»","Шахматки = золотая жила. На сайтах ПИК/Брусника/Атомстройкомплекс/ТЭН-Девелопмент/Стройтэк/ЛСР и др. интерактивная шахматка с поквартирным статусом (доступно/бронь/продано). Даёт площадь, комнатность, этаж, секцию, цену, дату продажи","Тех-план: воркер services/site_finder/sales_tracker.py + поадаптеру на каждого застройщика (brusnika_scraper.py, atomstroy_scraper.py...). Cron 1×в сутки. SPA-сайты — Playwright. SSR — httpx+BS4","Схема БД: apartments(id, jk_id, room_count, area_sqm, floor, section, price_rub, status, last_seen_at) + sales_history(apartment_id, sold_date, sold_price). Materialized views для velocity в радиусе X от точки","Три киллер-фичи из этих данных: A) Velocity Score в Site Finder — дополнительный 4-й критерий скоринга (сколько квартир продаётся/мес в радиусе 1км). B) Smart Unit-Mix в Generative — рекомендация долей 1/2/3-комн на основе реальных продаж в районе. C) Validation финмодели — бенчмарк прогноза выручки против факта по соседним ЖК","Это самый важный data moat: TestFit без РФ-данных, rTIM без site-selection и аналитики спроса. Через 6-12 мес накопления — уникальный источник данных для девелоперов, который не воспроизвести конкурентам быстро","План Discovery: Stage 2a нед.8-9 добавляется воркер sales_tracker параллельно парсеру ПКК. Реализуем 5-7 адаптеров (топ-застройщики Екбурга). К концу месяца 3 имеем 2-3 недели исторических данных","Целевые застройщики Екбурга для Discovery: Атомстройкомплекс, Брусника, ТЭН-Девелопмент, Стройтэк, Прогресс, УГМК-Застройщик, Кортрос, ЛСР-Урал, Forum-group, ПИК (если есть в ЕКБ)","Юридика: шахматки = публичные маркетинговые данные (без авторизации, серая зона мягче ЦИАН). Прецедентов исков застройщиков к парсерам практически нет (им нужны шахматки как воронка маркетинга). Для реестра ПО декларируем как «партнёрские интеграции с открытыми источниками застройщиков»","Анти-риски: 1) Сайт застройщика меняет вёрстку — скрейпер ломается, нужен Sentry alerting. 2) Юр-претензия от крупного застройщика — митигация через «партнёрство возамен аналитики» с топ-3 таргетов. 3) Низкое качество сайтов мелких застройщиков — берём только тех, у кого нормальный веб-интерфейс","Через 6 мес накопления: сезонные коэффициенты, absorption curves по типам квартир, ML-предсказание velocity для нового участка. Для Раунда А это идеальный narrative: «уникальная база продаж новостроек Свердловской обл., которой нет в открытых источниках и у западных игроков»"]}
{"type":"entity","name":"PlanA_AnalyticsFirst_Apr25","entityType":"decision_pending","observations":["Дата: 25 апреля 2026, вечер. Обсуждали с Антоном (второй разработчик)","Новые вводные: Антон сказал, что есть доступ ко всем сделкам для анализа. Детали по данным будут в понедельник 27 апреля 2026","Предложение Антона: сначала аналитика по продажам (что строить, какие квартиры, площади), потом всё остальное","Решение (предварительное, ждём детали): НЕ полный pivot. Перестановка порядка этапов: Stage 1 = Sales Analytics (нед 2-5), Stage 2 = Generative со Smart Defaults из аналитики (нед 6-10), Stage 3 = Site Finder с Velocity Score (нед 11-12)","Обоснование не полного pivot: Generative — главный дифференциатор против rTIM/TestFit. Без него конкурируем напрямую с ЕРЗ/ДОМ.РФ (у них 5 лет данных и команда). Аналитика становится мозгом для Generative и Site Finder, а не их заменой","Концепция «3 плитки»: ввод участок + класс жилья → (1) ЧТО СТРОИТЬ (unit-mix с velocity), (2) СКОЛЬКО ПРОСИТЬ (распределение цен м² по классам + тренд), (3) ЗА КАКОЕ ВРЕМЯ ПРОДАСТСЯ (absorption curves по АНАЛОГам). Кнопка «Сгенерировать концепцию» ведёт в Generative","Плюс нового плана: продаваемый артефакт уже после мес 1 (раньше был конец мес 2). Меньше технического риска. Другой ICP (инвестдепартамент вместо архитектуры)","КРИТИЧНО: «доступ ко всем сделкам» — это фундамент или мина. Бывают 4 сценария: 1) Легальный богатый ongoing (ЕРЗ Premium/банк/админ) → полный pivot, аналитика фундамент. 2) Легальный ограниченный → план A + шахматки параллельно для ongoing. 3) Серый канал → НЕ строим бизнес на этом, используем только «для себя». 4) Обещают но не дают → идём по плану шахматок, ждём","6 блоков вопросов к Антону на 27 апреля: Природа канала (что именно за доступ); Поля данных (цена/метраж/комнатность/покупатель?); Покрытие (регионы/история); Свежесть (разовая выгрузка или ongoing); Условия использования в коммерческом продукте; Цена доступа","Что делаем до пн (не останавливаемся, но с осторожностью): SSH-ключ, выбор хостинга (Beget/Timeweb), Stage 0 скелет уже сделан. НЕ начинаем Shapely геометрию или парсер ПКК — приоритет может сместиться","Шахматки застройщиков НЕ отменяются даже если данные Антона полные: 1) Сделки в Росреестре регистрируются с лагом 1-3 месяца. 2) Бронирования и доступность — сделки этого не показывают. 3) Маркетинговая цена vs фактическая различается","Сообщили Кене ответ Антону: направление в точку, но не полный pivot. Ждём детали по данным в пн. Вижу 6 блоков вопросов. От ответов зависит тип плана","Уточнение 25.04.2026 вечер: Антон подтвердил — речь идёт о ДДУ (Договорах Долевого Участия). Это идеальный источник для аналитики: ground truth по продажам новостроек, выше качеством чем шахматки","ДДУ поля стандартно: кадастровый номер квартиры, площадь, цена, дата регистрации, застройщик, ЖК. иногда комнатность/этаж/секция. ПН-поверхность: ПДн покупателя часто включены — обязательное обезличивание до записи в нашу БД (152-ФЗ)","Лаг ДДУ: 30-90 дней от реальной сделки до регистрации в Росреестре. Поэтому шахматки застройщиков НЕ отменяются — они дают 'today snapshot', ДДУ дают 'historical truth'","5 блоков к понедельнику (сужены до ДДУ-специфики): 1) Канал — держатель и договор (DOM.RF API/ЕРЗ Premium/банк/администрация/другое). 2) Поля (все ли обязательные + комнатность и ПДн). 3) Покрытие (регионы/история). 4) Свежесть (разовая/ongoing/real-time и лаг). 5) Условия коммерческого использования","Преимущество ДДУ над шахматками: ground truth по фактической цене (не маркетинговой), историческая глубина, юридически чистый источник (если канал легален), data moat относительно TestFit/rTIM"]}
{"type":"entity","name":"Runbook_VPS_Setup_Beget","entityType":"runbook","observations":["Источник: фактическая настройка сервера Jolly Yakov в Beget Cloud, 25.04.2026. Сервер 2 vCPU / 4GB RAM / 40GB NVMe / Ubuntu 24.04, IP 46.173.16.127","ШАГ 1: Создание сервера в cp.beget.com/cloud → Создать сервис → VPS → Standard 3+ GHz → 2 ядра/4GB/40GB. ОС: Ubuntu 24.04. Включить публичный IPv4. После создания сервер получает IP, root пароль выслан на email","ШАГ 2: Генерация SSH-ключа локально (если ещё нет). Windows PowerShell: ssh-keygen -t ed25519 -C 'gendesign-deploy' -f $HOME\\.ssh\\gendesign_deploy. Пароль оставить пустым (Enter Enter) — нужно для автодеплоя","ШАГ 3: Добавление публичного ключа на сервер через панель Beget. При проблемах со SSH (Connection reset, fail2ban) — войти через VNC терминал в браузере и добавить в ~/.ssh/authorized_keys","ШАГ 4: Первый вход по SSH с явным ключом. Команда: ssh -i $HOME\\.ssh\\gendesign_deploy root@<IP>. При первом коннекте спросит fingerprint — yes","ШАГ 5: На сервере (root): обновить пакеты 'apt update && apt upgrade -y'. Если [-f /var/run/reboot-required] то ребут. Установить hostname/timezone: hostnamectl set-hostname gendesign; timedatectl set-timezone Europe/Moscow","ШАГ 6: Создание non-root пользователя. adduser gendesign (задать сильный пароль, остальное Enter). usermod -aG sudo gendesign. Копия SSH-ключа root→gendesign: mkdir -p /home/gendesign/.ssh && cp ~/.ssh/authorized_keys /home/gendesign/.ssh/ && chown -R gendesign:gendesign /home/gendesign/.ssh && chmod 700 /home/gendesign/.ssh && chmod 600 /home/gendesign/.ssh/authorized_keys","ШАГ 7: Тест первого входа как gendesign. Важно: хранить root-сессию открытой как safety net до конца. В новом окне: ssh -i $HOME\\.ssh\\gendesign_deploy gendesign@<IP>. Проверка sudo: sudo whoami → root","ШАГ 8 (Windows-специфика): SSH config не создавать через Notepad — он добавляет .txt и сохраняет в UTF-8 с BOM. Правильный способ: PowerShell heredoc | Out-File -Encoding ascii -FilePath $HOME\\.ssh\\config. Блок Host: HostName <IP>, User gendesign, Port 22, IdentityFile ~/.ssh/gendesign_deploy, IdentitiesOnly yes, ServerAliveInterval 60. Критично включать IdentitiesOnly yes — иначе Windows OpenSSH перебирает все ключи и получает MaxAuthTries reset не дойдя до нужного","ШАГ 9: Отключение root-логина и паролей в SSH. ТОЛЬКО ПОСЛЕ подтверждения gendesign работает и sudo работает. sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak; sudo nano /etc/ssh/sshd_config → PermitRootLogin no, PasswordAuthentication no, PubkeyAuthentication yes. sudo sshd -t для валидации. sudo systemctl reload ssh","ШАГ 10: Критический тест в третьем окне: ssh gendesign → пускает по ключу. В четвёртом: ssh root@<IP> → должен отказать. Старую root-сессию закрываем только после этого","Распространённые грабли: 1) Connection reset при неверном пароле = fail2ban Beget. Обход через VNC. 2) Notepad вместо config пишет config.txt — проверять ls $HOME\\.ssh\\. 3) Windows OpenSSH без IdentitiesOnly перебирает все ключи. 4) Группа sudo не подхватывается без выхода-входа. 5) При UNPROTECTED PRIVATE KEY FILE использовать icacls /inheritance:r /grant:r '<имя>:(R)'","Статус 25.04.2026 вечер: Шаги 1-7+8 выполнены. gendesign@46.173.16.127 работает по ключу, sudo работает. Осталось: SSH hardening (Шаг 9), UFW firewall, установка Docker, клонирование репо в /opt/gendesign","Статус 25.04.2026 вечер (обновлён): Базовая настройка VPS завершена. gendesign@46.173.16.127 работает по ключу, sudo работает. UFW активен (22/80/443). SSH hardening: PermitRootLogin no, PasswordAuthentication no, PubkeyAuthentication yes через drop-in /etc/ssh/sshd_config.d/00-gendesign-hardening.conf (приоритет 00- перебивает cloud-init defaults). Docker и git установлены. Репо клонировано в /opt/gendesign через deploy key github_deploy. PostgreSQL+PostGIS и Redis работают в докер-компоуз. PostGIS_Version() = 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1","Осталось: GHCR setup (замена YCR на GHCR в deploy.yml + docker-compose.prod.yml), GitHub Secrets, Caddy reverse proxy, домен, первый автодеплой backend+frontend","ВЕХА 25.04.2026 вечер: Первый успешный автодеплой. GitHub Actions воркфлоу deploy.yml прошёл полный цикл: build обоих образов (backend ~2.5мин, frontend ~1мин) → push в GHCR (ghcr.io/lekss361/gendesign-backend, gendesign-frontend, приватные) → SSH на сервер → docker compose pull (с PAT-авторизацией) → up -d. /health отвечает {status:ok, environment:prod}","GHCR пакеты остаются ПРИВАТНЫМИ (решение пользователя для защиты алгоритмов). Сервер авторизуется в GHCR через PAT с read:packages, сохранён в ~/.docker/config.json. PAT с длительным сроком или без срока","Исправлены во время деплоя: backend Dockerfile (убрал невалидный conditional COPY для alembic, перешли на uv sync без --frozen до генерации lockfile); frontend package.json (react-leaflet 4→5 для совместимости с React 19); frontend Dockerfile (npm install --legacy-peer-deps вместо npm ci, пока нет lockfile); frontend/public/.gitkeep для Next.js standalone build","Статус инфраструктуры к 25.04.2026 19:00: VPS Beget работает (Москва, 2/4/40 NVMe). UFW + SSH hardening + non-root user. Docker compose prod поднят с 5 сервисами (postgres+redis+backend+frontend+caddy). GitHub Actions автодеплой работает на push в main. /health публичен внутри VM (127.0.0.1:8000)","Осталось до «infra-ready»: домен, Caddy TLS с Let's Encrypt на этот домен, регулярные pg_dump в Object Storage, frontend NEXT_PUBLIC_API_BASE_URL на реальный домен (сейчас пустая). И дальше — Stage 1 разработки по выбранному PlanA_AnalyticsFirst_Apr25 (после понедельника с Антоном по ДДУ-данным)"]}
{"type":"entity","name":"Hardlink_Test_Apr25","entityType":"test","observations":["Тестовая запись, дата 25.04.2026 поздний вечер","Цель: проверить, что после пересоздания хард-линка записи MCP попадают в репо-файл memory/memory-gendesign.jsonl","Ожидаемый результат: размер репо-файла увеличится, git status покажет modified","Наблюдение: предыдущий хард-линк разорвался (LinkType был null, синхронизация репо-файла с MCP-папкой прекратилась). Репо-файл был 16550 байт, источник 43957 байт","Если тест пройдёт (синхронизация восстановлена) — рабочий цикл из README снова валиден. Если не пройдёт — нужен sync-memory.ps1 скрипт или альтернатива"]}
{"type":"entity","name":"Domain_Setup_Apr26","entityType":"infrastructure","observations":["Дата: 26.04.2026","Домен: gendsgn.ru, регистрация в Beget, срок до 26.04.2027","Стоимость: 199 ₽ первый год, 420 ₽/год продление. Сравнение из браузера 26.04.2026: Reg.ru 169₽ первый год + ~890₽ продление; Timeweb 200/399; nic.ru 747₽ регистрация (премиум)","Решение: Beget — потому что (1) хостинг VPS уже там, единая админка и единая платежка для бухгалтерии; (2) продление 420₽ — лучшее на рынке; (3) free DNS включён","DNS-серверы: ns1.beget.com, ns2.beget.com (плюс ns1.beget.pro, ns2.beget.pro как backup)","A-записи прописаны 26.04.2026: @ (apex) и www → 46.173.16.127. Beget NS отдают корректно (проверено nslookup gendsgn.ru ns1.beget.com → 46.173.16.127). Публичные резолверы (8.8.8.8, 1.1.1.1) на 26.04 ещё NXDOMAIN — пропагация .ru registry → public DNS, ожидаемо 30 мин - 4 часа","Caddyfile обновлён под gendsgn.ru: основной site block с auto-TLS Let's Encrypt, www → 301 redirect на apex, :80 fallback для IP-доступа сохранён. Закоммичен 68e95aa, запушен в main. На VM не применён (старый deploy.yml не делает git pull)","deploy.yml будет дополнен `git fetch + reset --hard origin/main` + `caddy reload --config /etc/caddy/Caddyfile` после `up -d`. Закоммитим и запушим когда DNS пропагируется. Это финальный шаг для HTTPS","Важное правило отрасли: с 1 сентября 2026 владелец .ru-домена обязан иметь подтверждённую учётку ЕСИА (Госуслуги) — иначе домен не продлят. Для ИП/ООО — через ЭДО/СБИС. Касается всех регистраторов одинаково. К моменту продления (26.04.2027) ООО уже должно быть зарегистрировано — учёт без проблем"]}
{"type":"entity","name":"Sentry_Setup_Apr26","entityType":"infrastructure","observations":["Дата: 26.04.2026","Sentry организация: qqq (qqq-5y.sentry.io), free tier (5К ошибок + 10К транзакций / мес)","Sentry проект: gendesign-backend, платформа FastAPI, регион Frankfurt (ingest.de.sentry.io)","DSN сохранён в /opt/gendesign/backend/.env как SENTRY_DSN. На локальной машине — не нужен (Sentry init в backend/app/main.py условный — отключён если DSN пустой)","Конфиг init: sentry_sdk.init(dsn=settings.sentry_dsn, environment=settings.environment, traces_sample_rate=0.1) — 10% запросов трейсятся для performance","Алерты: «high priority» по умолчанию + email на alexandro361@gmail.com","Тестовое событие отправлено и получено 26.04.2026 — event_id 67f05bdd59234a608a828fa81f72ded5. Sentry интеграция работает на проде","Важная операционная заметка: docker compose restart НЕ перечитывает env_file. После правки backend/.env нужно `docker compose -f docker-compose.prod.yml up -d --force-recreate --no-deps backend`. Применимо к любым env-изменениям, не только Sentry","DSN — не критичный секрет (в frontend SDK всегда зашит публично в JS-бандл). Держим в .env, не в репе. Ротация при необходимости через Sentry → Settings → Client Keys (DSN) → New Key"]}
{"type":"entity","name":"OpsBundle_Apr26","entityType":"infrastructure","observations":["Дата: 26.04.2026","Подготовлен пакет инфраструктурных правок (в working tree, не закоммичено): Alembic baseline + TIGER cleanup + pre-commit + pg_dump backups + Makefile targets","Alembic: создан backend/alembic.ini + backend/alembic/env.py (импорт Base из app.core.db, моделей через app.models.*) + script.py.mako + versions/.gitkeep. Первая реальная миграция — в Stage 2a, когда Parcel-модель будет финализирована. Сейчас versions/ намеренно пуст","TIGER cleanup: backend/db/init/99_drop_unused_extensions.sql дропает postgis_tiger_geocoder + postgis_topology + fuzzystrmatch на свежем postgres-volume (через bind-mount ./backend/db/init:/docker-entrypoint-initdb.d:ro в обоих compose-файлах). Срабатывает только при первой инициализации пустого volume","Pre-commit: .pre-commit-config.yaml в корне (trailing-whitespace, end-of-file-fixer, ruff lint+format на backend/, prettier на frontend/, detect-private-key, check-yaml/toml). Pre-commit добавлен в dev-deps backend/pyproject.toml. Локально — `python -m pre_commit install` или `make pre-commit-install`","pg_dump: ops/backup.sh — cron-скрипт с опциональной выгрузкой в S3. Ретенция 7 дней локально. ops/restore.sh с защитой RESTORE_CONFIRM=yes","Makefile: добавлены `make migration NAME=...` и `make pre-commit-install`. `make migrate` использует `alembic` напрямую (uv нет в production-образе)","backend/Dockerfile: COPY alembic.ini + COPY alembic в обе стадии (builder и runner)","S3 для бэкапов: пока не настроено. Когда настроим Selectel или Yandex Object Storage, env-конфиг — /etc/default/gendesign-backup на VM, cron — `30 3 * * * /usr/local/bin/gendesign-backup`"]}
{"type":"entity","name":"Production_Wipe_Apr26","entityType":"event","observations":["Дата: 26.04.2026","Прод полностью пересоздан с нуля для чистого состояния. Не было критичных данных — БД содержала только postgis-defaults","Команды на VM: `docker compose down -v` → `docker rmi` GHCR-образов и базовых (caddy:2, postgis/postgis:16-3.4, redis:7-alpine) → `git pull --ff-only` (Caddyfile, compose) → `docker system prune -af --volumes`","Re-deploy через GitHub Actions Deploy → все 5 контейнеров поднялись с image-тегом 08a63f6 (главный коммит на момент wipe)","Состояние после re-deploy: postgres healthy, redis healthy (новый healthcheck), backend healthy (фикс curl-healthcheck в multi-stage Dockerfile), frontend up, caddy up. PostGIS 3.4 USE_GEOS=1 USE_PROJ=1","TIGER-мусор вернулся (как ожидалось) при свежей инициализации postgis-image. Будет автоматически удаляться при следующих wipe-ах когда применим OpsBundle_Apr26 (init-скрипт 99_drop_unused_extensions.sql)"]}
{"type":"entity","name":"DockerOps_Apr26","entityType":"infrastructure","observations":["Дата: 26.04.2026","Серия Docker-фиксов задеплоена в main: e22aeb9 (multi-stage + npm ci + healthcheck + same-origin API), d0909e6 (ruff fixes), 08a63f6 (mypy fixes), 68e95aa (real domain Caddyfile)","backend/Dockerfile: переписан на multi-stage (builder с build-essential + libgdal-dev + uv sync; runner только с runtime-либами libpq5, libgdal36, libproj25, libgeos-c1t64, libcairo2, libpango*, curl). Финальный образ 1.44 GB вместо ~2 GB. Запускается под non-root пользователем `app` (uid 1000)","backend curl healthcheck в docker-compose.prod.yml теперь работает (до этого был баг — curl не был установлен в slim-образе)","frontend/Dockerfile: переключён на `npm ci --legacy-peer-deps` вместо `npm install`. Запускается под `node` (uid 1000). package-lock.json закоммичен","docker-compose.prod.yml + dev: убран dead NEXT_PUBLIC_API_BASE_URL (Next.js bakes NEXT_PUBLIC_* на build-time, runtime override no-op). Frontend ходит на same-origin /api/* — в проде через Caddy, в dev через Next.js rewrites (BACKEND_URL env)","Caddyfile: исправлен баг — handle_path /api/* стрипал префикс /api, FastAPI router на /api/v1/* возвращал 404. Заменено на handle /api/*","backend/uv.lock сгенерирован (через docker run python:3.12-slim + pip install uv && uv lock). Дальнейшие билды детерминированы: `uv sync --frozen --no-dev`","Ruff config: ignore=['RUF001','RUF002','RUF003'] — проект русскоязычный, кириллица в комментариях/docstring (МСК-66 etc.) — норма, иначе постоянно ругается"]}
{"type":"entity","name":"HTTPS_Live_Apr26","entityType":"milestone","observations":["Дата: 26.04.2026, ~14:41 MSK","Прод официально живой на HTTPS: https://gendsgn.ru/ возвращает 200, https://gendsgn.ru/health → {\"status\":\"ok\",\"environment\":\"prod\"}, https://www.gendsgn.ru/ → 301 на apex","Цепочка: ЕСИА-верификация в Beget → реестр .ru обновился → DNS пропагировался к 8.8.8.8/1.1.1.1 → push deploy.yml с git-pull+caddy-reload не делался (юзер сделал руками на VM) → пришлось вычищать caddy_data volume чтобы сбросить старый retry-state на gendesign.example.ru и Let's Encrypt staging fallback → Caddy перезагрузился чисто → cert получен с production Let's Encrypt","Урок: при wipe `down -v` мы убрали весь caddy volume включая ACME-state. Если бы оставили — Caddy продолжал бы фоновые retry-задачи на старый плейсхолдер gendesign.example.ru, и accumulated failures могли бы триггернуть staging fallback. На будущее: `caddy reload` не сбрасывает retry queue — для чистого старта нужен `restart` или volume-wipe","GitHub-issues #1 (ЕСИА) и #2 (push deploy.yml) можно закрывать как done","Стек живет: HTTP/2 + HTTP/3 (alt-svc), Caddy reverse-proxy фронт+бэк, FastAPI корректно отвечает через /api/* префикс (handle вместо handle_path сработал)"]}
{"type":"entity","name":"DataSources_Analysis_Apr26","entityType":"research","observations":["Дата: 26.04.2026. Глубокий анализ источников данных для GenDesign — проверено через debug-браузер на наш.дом.рф","🥇 ГЛАВНАЯ НАХОДКА: ДОМ.РФ имеет ОТКРЫТЫЕ JSON API без аутентификации. Это меняет всё для Plan A и Site Finder","ДОМ.РФ Аналитика API (`naash.dom.rf/portal-analytics/api/`): /dictionaries/regions, /dictionaries/developers, /dashboard/by-room-count, /dashboard/by-flat-area, /dashboard/by-developer, /dashboard/by-region. Возвращают JSON: по каждому региону id, flatCount, area, и details — разбивка по комнатности (ONE/TWO/THREE/FOUR с площадями и %). Базовый URL хоста: https://xn--80az8a.xn--d1aqf.xn--p1ai (он же наш.дом.рф). Без auth, accept: application/json. Свердл. обл. id=66, flatCount=115205, area=5.67M м²","ДОМ.РФ Каталог квартир API (`/сервисы/api/kn/`): /flats/map?latitudePoint1=...&latitudePoint2=...&longitudePoint1=...&longitudePoint2=...&flatStatus=free,booked возвращает per-ЖК записи {objId, latitude, longitude, priceMin, objStatus}. /flats/filters даёт диапазоны фильтров. Auth: header `Authorization: Basic MTpqd2U=` (= base64('1:qwe')) — хардкод в фронте, действующий ключ. По Свердл. обл. видно 24 441 квартир в продаже","ДОМ.РФ доступные на per-flat фильтры (которые присутствуют в JSON): кол-во комнат (студия/1/2/3/4+), год сдачи (Сдан/2026/2027/2028+), цена (от 2.6М до 4.8 млрд), площадь (16-1001 м²), этаж (1-68), цена м² (82К-7.2М), отделка (без/черновая/предчистовая/чистовая/под ключ), класс (типовой/комфорт/бизнес/элитный), материал стен (блоки/кирпич/панель/монолит/монолит-кирпич), тип (жилое/нежилое), эскроу, безбарьерная среда, благоустройство, энергоэффективность, наличие апартаментов","ДОМ.РФ покрытие России: 2.4 млн квартир в строящихся домах, 118.7 млн м². По регионам ТОП-20 включает Свердл.обл (4-е место, 5.67М м²). По девелоперам ТОП-15: Самолет, ПИК, DOGMA, ТОЧНО, ФСК, Брусника, Setl Group, ЛСР и др.","ДОМ.РФ распределение площадей квартир в РФ: 0-25м²: 6%, 25-35м²: 17%, 35-45м²: 30% (мода), 45-55м²: 14%, 55-70м²: 20%, 70-85м²: 8%, 85-100м²: 3%, более 100м²: 2%. В среднем около 49 м² (118.7М/2.4М). Это ВАЖНЕЙШИЙ benchmark для smart unit-mix Plan A","ДОМ.РФ распределение по комнатности: 1-комн 54% (1.31М), 2-комн 32% (0.78М), 3-комн 12% (0.30М), 4+комн 1% (33К)","ДОМ.РФ есть еще API endpoints: Единый реестр застройщиков, Единый реестр МЖК, Единый реестр ЖСК, Единый реестр проблемных объектов, Реализация квартир в строящихся домах (динамика продаж!), Распроданность и стройготовность (что-то вроде velocity!). Все по naash.dom.rf/аналитика/*. Велоситит и распроданность — могут быть прокси для нашего sales_tracker без необходимости парсить шахматки","🥈 ВЫВОД: для Plan A не нужно ждать ДДУ-данные от Антона. ДОМ.РФ открыто отдает агрегаты + ground truth по объектам. Это юридически чистый канал ('через API ДОМ.РФ' можно официально декларировать в реестре ПО)","Overpass API (OpenStreetMap, https://overpass-api.de/api/interpreter): бесплатно, без авторизации. Синтаксис Overpass QL: `[out:json][timeout:25]; node[\"amenity\"=\"school\"](56.7,60.5,56.9,60.7); out body;` — все школы в bbox. Поддерживает radius `node(around:1000)[\"amenity\"=\"hospital\"]`. Релевантные tags для нас: amenity=school|hospital|clinic|kindergarten|university, public_transport=station+station=subway|tram|bus, shop=mall|supermarket, leisure=park|playground, highway=primary|secondary","Overpass rate limit: ~5 запросов/мин на IP. Для production — поднять свой mirror через Docker (overpass-api/docker-overpass-api), либо использовать кеш Redis (TTL 24-72 ч, POI редко меняются)","Росстат fedstat.ru (id=31452): 'Средняя цена 1 кв.м общей площади квартир на рынке жилья' — квартально по регионам РФ, разбивка первичка/вторичка, по типам квартир. Данные с 2000 по 2025. Скачивание SDMX/возможно CSV/XML. НЕТ публичного API. Подход: разовая выгрузка → Excel → загрузить в нашу БД, обновлять раз в квартал вручную","Минстрой РФ (minstroyrf.gov.ru): норматив средней рыночной стоимости 1 м² для расчета субсидий. Публикуется приказом Минстроя ежеквартально по всем регионам. Для Свердл. обл. ~85-95 тыс ₽/м² на 2025 год. Доступ: PDF приказа на сайте Минстроя, копия в КонсультантПлюс. Использовать как baseline для нашей финмодели","Главгосэкспертиза НЦС (gge.ru, был 404 на /ncs/, реальный URL на момент проверки изменился): нормативы цены строительства 1 м² по типам зданий + регионам. Используется для расчета бюджетов госзаказа. Публикуется приказом Минстроя ежегодно. Для частных девелоперов — сравнительный baseline 'минимальная себестоимость'. Найти актуальный URL через минстроя/КонсультантПлюс","ЕРЗ.РФ (erzrf.ru): главный конкурент по аналитике в РФ, премиум-доступ. Полные данные: реестр застройщиков, рейтинги ЖК, статистика продаж, вакантность. Цена доступа на сайте не раскрыта — нужно запрашивать. Industry knowledge: ~50-100 тыс ₽/год за подписку на регион, ~500 тыс ₽/год за всю РФ. У них есть API B2B (под NDA). Использовать как 'договорённости в проработке' для инвесторов Раунда А, реально подписываться когда будет budget","СберИндекс (sberindex.ru, не открылся через WebFetch — 'unable to verify the first certificate', попробовать через браузер позже): бесплатные агрегаты Сбера по экономике РФ, включая жилье. Покрытие хорошее, обновление часто. Использовать для cross-validation с ДОМ.РФ + Росстат","ДомКлик (domclick.ru): listings первички и вторички + ИПОТЕЧНАЯ статистика. Открытый каталог с ценами/площадями. Анти-бот защита есть, но не очень жёсткая. Публичный sitemap.xml. Подход: спарсить раз в неделю свердл.обл (~50 тыс листингов), сохранить в БД с history. Для cross-check ДОМ.РФ цен","ЦИАН (cian.ru): крупнейший аггрегатор РФ. Cloudflare защита + rate limit. Парсить рискованно (юридически серая зона + блокировки). Готовые либы: cianparser, cianscraper на GitHub. Использовать ОЧЕНЬ ограниченно (200-500 листингов на район для калибровки), не как основной источник","Авито Недвижимость (avito.ru): аналогично ЦИАНу — антибот, Cloudflare. Есть платный B2B API (через avito_business — недешево). Для Discovery — пропускаем","Яндекс.Недвижимость (realty.ya.ru): listings, иногда XML feed для риелторских CRM. Есть Yandex Realty API (документированный, но enterprise). Для Discovery — пропускаем","Шахматки застройщиков (Брусника, Атомстройкомплекс и т.д.): по факту самый ground-truth источник для today snapshot. SPA-сайты — Playwright. SSR — httpx+BS4. План в Stage 2a/sales_tracker уже описан в SalesTracking_Strategy_Apr25. ОДНАКО — теперь когда у нас есть 'Реализация квартир' из ДОМ.РФ, шахматки могут быть downgrade-нуты до 'дополнительной валидации'","Другие источники (mention only): ОКТМО (для region IDs), ФИАС (адреса), Росреестр ПКК (только границы участков, без ДДУ), ДомРФ.Bank (ипотечные ставки — отдельный поток для финмодели), ЖКХ.МО.РФ (управляющие компании — для оценки операционных расходов). Всё в реестре российских данных.","ИТОГ — приоритеты по источникам для Discovery MVP (от 1 = критично до 5 = можно отложить):","1) ДОМ.РФ portal-analytics + api/kn/flats — бесплатно, открыто, ground truth, ВСЁ нужное для Plan A и Site Finder. Базовый источник","2) Overpass API (OSM) — бесплатно, для POI вокруг участков. Site Finder скоринг","3) Росстат fedstat.ru — квартальный baseline цен, разовая выгрузка → БД. Финмодель + cross-validation","4) Минстрой норматив + НЦС — для реалистичной себестоимости в финмодели","5) Шахматки 5-7 застройщиков Екбурга — дополнительная свежесть к ДОМ.РФ. Stage 2a опционально","Приоритет 1 ('вынес' ДДУ-данные): ВСЁ можно собрать сегодня вечером без Антона. Это разбивает блокировку #10 — даже если канал ДДУ серый/нет — Plan A 'analytics first' технически выполним на ДОМ.РФ data","Метрики, которые мы можем считать прямо из ДОМ.РФ для Plan A '3 плитки':","ПЛИТКА 1 — ЧТО СТРОИТЬ: для участка → район → ID региона → /portal-analytics/api/dashboard/by-room-count?regionId=X → распределение комнатности что строится. Дополнительно /dashboard/by-flat-area по тому же региону → распределение площадей. Smart unit-mix готов","ПЛИТКА 2 — ПО КАКОЙ ЦЕНЕ: для координат (lat,lon) → запрос /api/kn/flats/map в bbox 5km → собрать все priceMin → median + p10/p90 → диапазон цен в районе. Cross-check с Росстатом по региону","ПЛИТКА 3 — ЗА КАКОЕ ВРЕМЯ: /аналитика/реализация_строящихся_квартир + /распроданность-стройготовность по региону → absorption curves по комнатностям. Если бы у Антона были ДДУ — было бы точнее, но и без них есть прокси-сигнал","Юридическая безопасность для реестра ПО: всё что используем — ОФИЦИАЛЬНО открытые источники (ДОМ.РФ, Росстат, Минстрой, OSM). Никакого скрейпинга в обязательных каналах. Шахматки и ЦИАН — опциональные, помечаем как 'партнерские интеграции в проработке'","Implementation effort estimates (часы разработчика):","ДОМ.РФ analytics API клиент + кеш Redis: 4-6 часов","ДОМ.РФ flats/map per-объект клиент с пагинацией bbox: 6-8 часов","Overpass клиент + tag mapping для POI: 3-4 часа","Росстат разовая выгрузка + ETL в БД: 2-3 часа","Минстрой парсинг приказа PDF → таблица: 2-3 часа","СУММАРНО: 17-24 часа на полный data layer без Антона"]}
{"type":"entity","name":"DomRF_Integration_Docs_Apr26","entityType":"api_spec","observations":["Дата: 26.04.2026. Официальная страница интеграции ДОМ.РФ ЕИСЖС: https://наш.дом.рф/интеграция","⚠ ЮРИДИЧЕСКИЙ СТАТУС API СЖС: предназначено ТОЛЬКО ДЛЯ УПОЛНОМОЧЕННЫХ БАНКОВ согласно Постановлению Правительства РФ № 697 от 18.06.2018. Напрямую подключиться НЕ МОЖЕМ — мы не банк. Но публичный фронт-API наш.дом.рф (то что мы выяснили) легален и доступен всем.","5 различных API в составе ЕИСЖС (вкладки на странице /интеграция):","1) API СЖС (Сведения о Жилищном Строительстве) — главное API для банков, даёт данные по застройщикам, ГК, ЖК, объектам строительства. Это та же информация что на наш.дом.рф в публичной форме.","2) API Уведомления ОПО — опасные производственные объекты. Не наш.","3) API Агрегатор ПФ — Проектное Финансирование, инфо о договорах эскроу. Для банков.","4) API НСИ — Нормативно-Справочная Информация, классификаторы. Справочники.","5) Сервисы СМЭВ — Межведомственное Электронное Взаимодействие. Для госорганов.","Официальные документы на скачивание (все DOCX/PDF публичные):","Соглашение об информационном взаимодействии v5.1 (08.02.2026): /site/binaries/content/assets/domrf/support/developer/agreement/соглашение-об-информационном-взаимодействии.-v5.1..docx — юридический договор присоединения по ст. 428 ГК РФ.","Презентация API СЖС v2 (03.12.2020): /site/binaries/content/assets/domrf/support/developer/presentation/еисжс-апи-сжс_v2.pdf — PDF обзор возможностей.","Спецификация API СЖС v1.3.0 (31.10.2020): /site/binaries/content/assets/domrf/support/developer/specification/api-сжс.-спецификация-api-v1.3.0.docx — полный OpenAPI-style документ с методами, форматами и ограничениями. Это бы хорошо разобрать для выявления всех полей и эндпоинтов, но спецификация для банковского API — форматы могут отличаться от нашего фронт-API.","Регламент информационного взаимодействия v1.5 (06.10.2020) + в тексте страницы упоминается v1.4: /site/binaries/content/assets/domrf/support/developer/reglament/еисжс-регламент-информационного-взаимодействия-участников-v1_5.docx (и v1_4.docx)","На странице есть кнопка 'ЗАГРУЗИТЬ ЕЩЕ' — вероятно в полном списке есть WSDL/OpenAPI в машинно-читаемом формате.","Официальный 7-шаговый flow подключения к API СЖС (для банков):","1. Ознакомление с Регламентом информационного взаимодействия","2. Запрос на nash@domrf.ru → назначается менеджер ЕИСЖС","3. Подписать 2 экземпляра Соглашения и ОТПРАВИТЬ физической почтой в ПАО ДОМ.РФ по адресу: 125009, г. Москва, Воздвиженка, д. 10 (с пометкой 'в ЕИСЖС')","4. Настройка информационной системы на своей стороне","5. Заявка на подключение к интеграционной (тестовой) среде → физпочта","6. Тестирование + протокол функционального тестирования","7. Заявка на промышленную среду → физпочта. Всего процесс занимает от 1 до 3 месяцев.","КОНТАКТЫ: nash@domrf.ru, 8-800-755-55-05, ПАО ДОМ.РФ, 125009 Москва, Воздвиженка 10.","СТРАТЕГИЧЕСКИЙ вывод для GenDesign:","Нам самим с API СЖС официально подключиться НЕЛЬЗЯ — по ПП №697 это только для уполномоченных кредитных организаций с эскроу-счетами. Имеет смысл искать банка-партнёра на этапе Раунд А или позже — бы их вход давал нам связку с банковским API. Банк ДОМ.РФ или Сбер — логичные partner candidates.","Но в Discovery не нужно — публичный фронт-API наш.дом.рф (описан в DomRF_API_Snapshot_Apr26 и связанных) даёт 99% того же что B2B-API. Разница: официальный API имеет SLA и stable contracts, фронт-API может измениться без уведомления.","Для реестра ПО: в заявке используем формулировку 'интеграция с открытыми данными ЕИСЖС ДОМ.РФ' — описываем публичные эндпоинты. Не 'Подключение к API СЖС' — это юридически неправда."]}
{"type":"entity","name":"DomRF_Tab10_MortgageRates_Apr26","entityType":"api_spec","observations":["Дата: 26.04.2026. Вкладка 10/12: Мониторинг ипотечных ставок","URL: /аналитика/ставки_предложений_по_ипотеке","Базовый API: /аналитика/api/mortgage-rates/*","Endpoints (все GET, ответ в формате {data: [...]}):","/mortgage-rates/reports — список 6 типов отчетов (id 1-6, name, date)","/mortgage-rates/reports/calendar — календарь доступных срезов (даты + перечень отчетов на каждую дату)","/mortgage-rates/reports/{reportId}/values/{columnId} — значения по банкам для колонки","Типы отчетов (reportId): 1=Рыночные продукты (квартира), 2=С господдержкой, 3=ИЖС, 4=Первичный рынок, 5=Вторичный рынок, 6=Рефинансирование","Колонки (columnId, для отчета типа 1): 1=Первичный рынок, 2=Вторичный, 3=Рефинансирование","Поля респонса /values/: bankId, value (ставка %), valueDelta, valueComment (текстовая приписка про скидки), needApprove","Пример данных на 19-04-2026: Сбербанк 20.2% (первичка), ВТБ 19.9%, с господдержкой 6%","Средние по рынку: Первичка 19.9%, Вторичка 19.59%, Рефинансирование 18.81%","Страница SSR-бакена — все данные в __NEXT_DATA__.props.initialState.mortgageOffers (reports, filters, tableData, detailedTableData, pdf)","Для GenDesign: полезно для финмодели — вход для расчета платежеспособности по концепту"]}
{"type":"entity","name":"DomRF_Tab11_MortgageStats_Apr26","entityType":"api_spec","observations":["Дата: 26.04.2026. Вкладка 11/12: Статистика по рынку ипотеки","URL: /аналитика/ипотечноередитование","Базовый API: /portal-analytics/api/mortgage/* + общие /base/* /comparison/* /building/*","/portal-analytics/api/mortgage/reporting_periods (GET) — доступные периоды по ипотеке","/portal-analytics/api/mortgage/dashboard/general (POST) — ОБЩИЙ дэшборд с фильтрами в body","/portal-analytics/api/mortgage/dashboard/details (POST) — детальный дэшборд","Справочники (те же что в вкладке 9 'Ввод жилья'):","/portal-analytics/api/base/dictionaries/period_types","/portal-analytics/api/base/dictionaries/region_with_autonomous","/portal-analytics/api/base/dictionaries/currencies","/portal-analytics/api/base/dictionaries/credit_types — виды кредитов (полезный для фильтров: ипотека под жилое/ИЖС/рефин.)","/portal-analytics/api/base/dictionaries/building_types","/portal-analytics/api/comparison/regions (POST) — кросс-региональное сравнение","/portal-analytics/api/building/reporting_periods_combined","ВАЖНО: dashboard/general и dashboard/details — POST с JSON в body. Формат body не снят на этом шаге (нужно поимать request body через list_network_requests при необходимости)","Парная вкладка 9 (Ввод жилья) использует /building/* + те же справочники. Это один бэкенд-модуль с разными dashboard'ами","Для GenDesign: данные по выданным ипотечным кредитам (объемы, кол-во, регионы) — полезно как прокси платежеспособности рынка"]}
{"type":"entity","name":"DomRF_Tab12_StatRows_Apr26","entityType":"api_spec","observations":["Дата: 26.04.2026. Вкладка 12/12: Статистические ряды жилищного строительства","URL: /аналитика/статистические_ряды","Это НЕ интерактивная вкладка, а КАТАЛОГ ссылок на XLSX-файлы со статистикой","Серверный endpoint (для SSR Next.js): GET /api/document/pages/xlsdashboard — вертает 401 Unauthorized для Basic MTpqd2U= (требует server-side токен, не доступен с клиента)","Структура ответа (из SSR-bundle): {items:{'domrf:blokItem':[...]}} — CMS-формат Domrf с титулами, группами и ссылками на файлы","Практически данные берутся из __NEXT_DATA__.props.initialState.housingData.list — иерархия: блоки → группы → файлы (text, link, date)","Прямая ссылка на XLSX (публичная, без auth): /site/binaries/content/assets/domrf/xlsdashboard/{filename}.xlsx","Примеры XLSX:","01_01_stockvariablesexsales.xlsx — Сведения о МКД по 214-ФЗ (РФ, регионы, ГК, НП, план. стоимость)","01_01_stockvariableskrt.xlsx — МКД по КРТ (комплексное развитие территорий)","01_02_flowvariables.xlsx — ПРОЕКТНЫЕ ДЕКЛАРАЦИИ (размещенные за период)","+ ДДУ (договоры участия в долевом строительстве) сводные","Дата всех файлов: 01.04.2026 (обновляются 1-го и 25-го числа)","Для GenDesign: ЭТО КЛАД — все официальные сводки ДОМ.РФ в XLSX-формате без лимитов, отличный способ получить базовые ряды без парсинга web-вызовов. Скачивать раз в месяц скриптом","Полный список XLSX-категорий можно вывести из __NEXT_DATA__.housingData (при SSR рендере страницы) — SSR-рендер + grep линков из разметки = список всех файлов"]}
{"type":"entity","name":"DomRF_Architecture_Apr26","entityType":"api_spec","observations":["Дата: 26.04.2026. Общая архитектура фронт-API наш.дом.рф для раздела АНАЛИТИКА.","Сайт — Next.js SSR. Данные подгружаются в __NEXT_DATA__ на SSR-этапе с бэкенда. На клиенте XHR файрит только при взаимодействии с фильтрами.","Используются 3 разных базовых пути:","(1) /portal-analytics/api/* — ОСНОВНОЙ публичный бэкенд, без авторизации. Основные аналитические вызовы.","(2) /аналитика/api/* — прокси через Next.js SSR-сервер к внутреннему API. Без авторизации. Для escrow, ddu, project finance, rpp, mortgage-rates, dictionary.","(3) /api/* — внутренний сервер (Express, x-powered-by). 401 без токена. Не Basic MTpqd2U= (требует server-side токен). Для /document/pages/* и реестров.","rate-limit эмпирически ~5 RPS → 502/429 при превышении","Cache-Control: max-age=900 (15 мин) — нет смысла чаще 15 мин ходить за одним и тем же ресурсом","User-Agent: ставить осмысленный, напр. 'GenDesign-DataSync/0.1 (https://gendsgn.ru)'","Юр. статус: парсинг публичного портала. Официальные спеки СЖС/НСИ/УОПО/АПФ совсем другой канал (OAuth2 + JWT для банков) — см. DomRF_OfficialSpecs_vs_FrontAPI_Apr26."]}
{"type":"entity","name":"DomRF_Tab1_HousingIndicators_Apr26","entityType":"api_spec","observations":["Вкладка 1/12: Основные показатели жилищного строительства.","URL: /аналитика/показатели_жилищного_строительства","Redux slice: housingConstructionIndicators. SSR-бакеные (клиент не файрит XHR при фильтрах)","Endpoints (group-1, /portal-analytics/api/*):","/dashboard/by-region?regionId={id} — регионы","/dashboard/by-developer?devId={id} — девелоперы","/dashboard/by-room-count?regionId={id} — комнатность","/dashboard/by-flat-area?regionId={id} — площадь","Параметры: regionId, devId, repYear, repMonth","Поля респонса (из __NEXT_DATA__): repYear, repMonth, type, subject (region code), subjectDesc, devCnt, rnsCnt, rpdCnt, objCnt, generalSquareSum, livingSquareSum, livingElemSum, escrowDevCnt/RnsCnt/RpdCnt/ObjCnt, escrowGeneralSquareSum, escrowLivingSquareSum, escrowLivingElemSum, zosgDevCnt/etc (эскроу/компфонд)","Этот endpoint = ПЛИТКА 1 для Plan A (что строить)"]}
{"type":"entity","name":"DomRF_Tab2_LaunchAndCommissioning_Apr26","entityType":"api_spec","observations":["Вкладка 2/12: Запуски и вводы МКД по 214-ФЗ.","URL: /аналитика/запуски-и-вводы","Базовый путь: /portal-analytics/api/launch/*","Суффиксы: 'app' = запуски/РНС (applications на строительство), 'rnv' = вводы (разрешение на ввод)","/launch/filters?repYear=2025 — доступные фильтры за год","/launch/obj-class/table?calculationType=SQUARE&repYear=2025 — распределение по классу (Типовой/Комфорт/Бизнес/Элитный)","/launch/developers/{app|rnv}?calculationType=SQUARE&repYear=2025&size=15 — рейтинг девелоперов","/launch/federal-districts/{app|rnv} — рейтинг ФО","/launch/regions/{app|rnv} — рейтинг регионов","/launch/areas/{app|rnv} — рейтинг населённых пунктов","Параметры: calculationType (SQUARE | HOUSES | FLATS), repYear, period (YEAR|MONTH), size (для рейтингов, дефолт 15)","+ /аналитика/api/dictionary/glossary — словарь терминов"]}
{"type":"entity","name":"DomRF_Tab3_ProjectFinance_Apr26","entityType":"api_spec","observations":["Вкладка 3/12: Регионы жилищного строительства / Долевое строительство и проектное финансирование.","URL: /аналитика/долевое_строительство","Базовый путь: /аналитика/api/project/finance/*","/project/finance/allDate — все доступные даты срезов","/project/finance/lastDate — последняя доступная дата","/project/finance/dashboard?dateDay=DD-MM-YYYY — полный dashboard на дату (проектное финансирование с разбивкой по регионам)","Формат даты: DD-MM-YYYY (НЕ ISO и НЕ YYYY-MM-DD!)"]}
{"type":"entity","name":"DomRF_Tab4_DevelopersDashboard_Apr26","entityType":"api_spec","observations":["Вкладка 4/12: Девелоперы жилищного строительства (рейтинг ГК).","URL: /аналитика/жилищное_строительство","Redux slice: dashboard. Полностью SSR — клиентских XHR не было выявлено при фильтрах.","Endpoints (все из group-1):","/portal-analytics/api/dashboard/by-developer — рейтинг девелоперов (основной)","/portal-analytics/api/dictionaries/developers — справочник 2734 девелоперов (id, name)","Id-формат: '{groupId}_{devId}' напр. '9333_0' (ГК) или '0_14583' (застройщик)"]}
{"type":"entity","name":"DomRF_Tab5_Escrow_Apr26","entityType":"api_spec","observations":["Вкладка 5/12: Рейтинг банков со счетами эскроу.","URL: /аналитика/эскроу","Базовый путь: /аналитика/api/escrow/*","/escrow/allDate — лист доступных дат срезов","/escrow/lastDate — последняя дата (из bundle, видимы в коде но не вызван на SSR)","/escrow?date=01-04-2026&withGroups=true&sort=guarantyEscrowRnsCnt:desc&subjectTypes=rf_bank&limit=9999 — рейтинг банков","Параметры: date (DD-MM-YYYY), withGroups (true/false), sort (поле:asc|desc), subjectTypes (rf_bank), limit","Сорты: guarantyEscrowRnsCnt, escrowDeposits, projectFinanceVolume","Полезно для finmodel в GenDesign — выбор банка-партнёра"]}
{"type":"entity","name":"DomRF_Tab6_Realization_Apr26","entityType":"api_spec","observations":["Вкладка 6/12: Реализация квартир в строящихся домах.","URL: /аналитика/реализация_строящихся_квартир","Базовый путь: /аналитика/api/rpp/* (rpp = реализация продаж)","/rpp/total?regionCode=66&repMonth=3&repYear=2026 — итоговые показатели","/rpp/housing?regionCode=66&repMonth=3&repYear=2026 — по жилью","/rpp/readyYear?regionCode=66&repMonth=3&repYear=2026 — по годам готовности","/rpp/developer?typeSquare=total&regionCode=66&repMonth=3&repYear=2026 — по девелоперам","/rpp/developer?developerOrder=totalSquare:desc — с сортировкой","Параметры: regionCode (66=Свердл.обл), repMonth, repYear, typeSquare (total|living)","Это КЛЮЧЕВОЙ endpoint для Plan A ПЛИТКИ 3 (velocity продаж)"]}
{"type":"entity","name":"DomRF_Tab7_ReadyConstruction_Apr26","entityType":"api_spec","observations":["Вкладка 7/12: Распроданность и стройготовность.","URL: /аналитика/распроданность-стройготовность","Базовый путь: /portal-analytics/api/ready-construction/*","/ready-construction/filters?repMonth=3&repYear=2026 — доступные фильтры","/ready-construction/charts?repMonth=3&repYear=2026 — графики","/ready-construction/dynamics?dynamicChartType=readyPercChart,soldPercChart,soldReadyPercChart,squareSumChart — динамика по периодам","/ready-construction/index?repMonth=3&repYear=2026 — индексы распроданности/готовности","/ready-construction/ready-year-charts?repMonth=3&repYear=2026 — распределение по годам сдачи","Это второй КЛЮЧЕВОЙ endpoint для velocity-tracking в GenDesign (sold% / ready% / soldReady%)"]}
{"type":"entity","name":"DomRF_Tab8_Quartirografia_Apr26","entityType":"api_spec","observations":["Вкладка 8/12: Характеристики строящихся квартир (квартирография).","URL: /аналитика/квартирография","Использует те же endpoints что и Tab1 (Показатели):","/portal-analytics/api/dashboard/by-room-count — комнатность (ONE/TWO/THREE/FOUR)","/portal-analytics/api/dashboard/by-flat-area — площадь (бакеты 0-25, 25-35, 35-45, 45-55, 55-70, 70-85, 85-100, 100+)","/portal-analytics/api/dashboard/by-developer?isPDF=false","/portal-analytics/api/dashboard/by-region?isPDF=false","/portal-analytics/api/dictionaries/developers","/portal-analytics/api/dictionaries/regions","+ /аналитика/api/dictionary/glossary","Это КЛЮЧЕВОЙ endpoint для Plan A ПЛИТКИ 1 (smart unit-mix)"]}
{"type":"entity","name":"DomRF_Tab9_BuildingCommissioning_Apr26","entityType":"api_spec","observations":["Вкладка 9/12: Ввод жилья в эксплуатацию.","URL: /аналитика/ввод_жилья","Базовый путь: /portal-analytics/api/building/* + /portal-analytics/api/base/dictionaries/* + /comparison/regions","/building/reporting_periods (GET) — доступные периоды","/building/reporting_periods_combined (GET) — сводные периоды","/building/summary/data (POST) — сводная дата по вводу (фильтры в body)","/comparison/regions (POST) — сравнение регионов","/base/dictionaries/period_types — типы периодов","/base/dictionaries/region_with_autonomous — регионы включая АО","/base/dictionaries/currencies — валюты","/base/dictionaries/credit_types — типы кредитов","/base/dictionaries/building_types — типы зданий","Отличие от других: POST-методы с JSON фильтрами в body. Парная с Tab11 (Ипотечное кредитование) — используют один бэкенд-модуль"]}
{"type":"entity","name":"DomRF_PlanA_Mapping_Apr26","entityType":"research","observations":["Критические endpoints ДОМ.РФ для Plan A '3 плитки' в GenDesign Discovery (состояние на 26.04.2026):","ПЛИТКА 1 (ЧТО СТРОИТЬ — smart unit-mix):","/portal-analytics/api/dashboard/by-room-count?regionId=X — распределение по комнатности","/portal-analytics/api/dashboard/by-flat-area?regionId=X — распределение по площади","ПЛИТКА 2 (ПО КАКОЙ ЦЕНЕ):","/сервисы/api/kn/flats?regions=X (per-flat с priceMin / pricePerSquareMeter, см. DomRF_API_KnFlats_Apr26)","ПЛИТКА 3 (ЗА КАКОЕ ВРЕМЯ — velocity):","/portal-analytics/api/ready-construction/* (см. Tab7) — sold%/ready%/soldReady%","/аналитика/api/rpp/* (см. Tab6) — velocity продаж по девелоперам","ОСОБОЕ ОТКРЫТИЕ: ready-construction и rpp — реальные показатели продаж (sold/ready %), без необходимости парсить шахматки застройщиков. Для Plan A absorption этого достаточно","Дополнительные источники:","Tab5 рейтинг банков эскроу — выбор банка-партнёра для finmodel","Tab10 ставки ипотеки — вход для расчета платежеспособности","Tab12 XLSX-каталог — официальные сводки по 214-ФЗ без лимитов (раз в месяц)","Tab2 launch — понимание размера рынка в регионе","Tab3 долевое — проектное финансирование по регионам"]}
{"type":"entity","name":"DomRF_Host_Apr26","entityType":"api_spec","observations":["Base URL: https://xn--80az8a.xn--d1aqf.xn--p1ai (он же наш.дом.рф)","Используй punycode-форму для прямых HTTP-вызовов из Python/Node — некоторые HTTP-клиенты ломаются на IDN","Backup: https://наш.дом.рф — требует поддержки IDN на стороне клиента","AUTH по группам:","Группа A (no auth): /portal-analytics/api/* и /portal-kn/api/*","Группа B (auth): /сервисы/api/kn/* — header `Authorization: Basic MTpqd2U=` (base64 от '1:qwe'). Технический токен фронта, хардкоден в JS, бессрочен","Группа C (server-side only): /api/* — 401 без токена, Basic MTpqd2U= НЕ подходит. Доступен только с SSR Next.js","Rate limit эмпирически: 5 RPS безопасно, 10+ → 502/429","Cache-Control: max-age=900 (15 мин) на /сервисы/api/kn/*","Без документированных лимитов (в отличие от официальных спек)","При 502 — экспоненциальный backoff: 5s, 30s, 5min. Если 5 мин не помогло — alert в Sentry","Поддержка: nash@domrf.ru, 8-800-755-55-05. B2B энтерпрайз-API: https://наш.дом.рф/сервисы для бизнеса"]}
{"type":"entity","name":"DomRF_API_PortalKn_Apr26","entityType":"api_spec","observations":["Группа B бэкенда ДОМ.РФ: /portal-kn/api/* — без авторизации. Ответственна за SEO/portal-сводки и географию.","GET /portal-kn/api/kn/places → {regions:[{regionCd, regionName, cities:[]}]} — регионы без городов","GET /portal-kn/api/kn/places?regionCd=66 → один регион с массивом cities:[{cityCds:[], cityName}]. По Свердл.обл ~30 городов","GET /portal-kn/api/sales/portal?flatStatus=free,booked&regions=66 → плоский array objId всех ЖК с продажами в регионе. По Свердл.обл — 283 ЖК","GET /portal-kn/api/kn/seo/aggregations?objStatus=0&regionCd=66 → {livingObjBlock, nonlivingObjBlock} с агрегатами региона: {objNumber, flatsNumber, devNumber, maxPrice, minPrice, avgPrice, avgMeterPrice, maxSquare, minSquare, minObjReadyDt}","USE CASE: получить список всех ЖК в регионе одним запросом, затем обогащать через /сервисы/api/kn/object?objId={N}"]}
{"type":"entity","name":"DomRF_API_KnObject_Apr26","entityType":"api_spec","observations":["Группа C: GET /сервисы/api/kn/object?objId={N} → полные данные одного ЖК. Auth: Basic MTpqd2U=","Поддерживает фильтр ?devId={devId} вместо objId — получаешь все объекты застройщика","Поля респонса (30+):","hobjId, objId — идентификаторы","developer{devId, devInn, shortName, fullName, groupName, orgForm, companyGroup} — застройщик","rpdRegionCd — код региона ПД","objAddr, shortAddr — адрес и его короткая форма","metro{id, name, line, color, time, isWalk} — ближайшее метро","freeFlatsInfo{priceMin, numberFlats} — свободные квартиры","objCommercNm — коммерческое название ЖК","objFloorMin, objFloorMax — диапазон этажности","objElemLivingCnt — количество жилых элементов","objSquareLiving — жилая площадь","objReady100PercDt — дата 100% готовности","latitude, longitude — координаты","siteStatus, objGuarantyEscrowFlg — статус и флаг эскроу","residentialBuildings — подъезды/секции","rpdNum, pdId — номер ПД и ид","buildType — тип строительства","hobjRenderPhotoUrl — attachmentId рендера ЖК (для /api/ext/file)","objPriceAVG — средняя цена","objPublDt — дата публикации","aiDescription — AI-сгенерированное описание ЖК"]}
{"type":"entity","name":"DomRF_API_KnFlats_Apr26","entityType":"api_spec","observations":["Группа C: per-flat endpoints. Auth: Basic MTpqd2U=","GET /сервисы/api/kn/flats?regions=66&offset=0&limit=N&flatStatus=free,booked → per-flat данные (17 полей). По Свердл.обл — 24 441 квартира","Поля /flats: id, odsId (objId/sectionNum/flatNum), elemId (UUID), type, number, isStudio, totalArea, livingArea, rooms, status (free/booked/sold), price, pricePerSquareMeter, priceChangeDate, socialMortgage, numberFloors, floor, image{attachmentId, type=layout}, objInfo{hobjId, objCommercNm, objAddr, objTransferPlanDt, objReady100PercDt}","⚠ priceChangeDate и status — ключевые поля для velocity-tracking. Дифф по дням → absorption rate","GET /сервисы/api/kn/flats/map?latitudePoint1=&latitudePoint2=&longitudePoint1=&longitudePoint2=&flatStatus=free,booked&regions=66 → per-ЖК в bbox: {data:{list:[{objId, objStatus, latitude, longitude, priceMin}]}}","Это база для Site Finder в GenDesign: bbox 5км вокруг участка","GET /сервисы/api/kn/flats/filters?regions=66&flatStatus=free,booked → диапазоны всех фильтров: {data:{meta:{list:[{name:'priceMin', values:['2644800']}, {name:'floorMin'}, {name:'areaMin'}, ...]}}}. Для UI sliders","GET /сервисы/api/kn/dataForFilters → диапазон дат публикаций: {data:{min, max}}","USE CASE выкачки: limit=500 в цикле offset+=500. По Свердл.обл — 49 запросов = ~10 секунд при 5 RPS"]}
{"type":"entity","name":"DomRF_API_KnDicts_Apr26","entityType":"api_spec","observations":["Группа C: справочники и фасеты /сервисы/api/kn/*. Auth: Basic MTpqd2U=","GET /сервисы/api/kn/meta?place=66&objStatus=0 → доступные значения объектных фильтров: objClass, energyEff [6,7,8,9], reasonProblemId, mechanism (7=эскроу, 6=без эскроу), wall, transferFlg, dduFlg, objTypeCd, objStatus, soldOut","GET /сервисы/api/kn/developers?objStatus=0&place=66&offset=0&limit=N → застройщики в регионе: {data:{list:[{id, devGkId, devInn, name}], total}}. По Свердл.обл 170+","GET /сервисы/api/kn/devGk?place=66&objStatus=0&offset=0&limit=N → группы компаний: {data:{list:[{id, name}], total:58}}. PRINZIP, BAZA Development, Prospect Group и т.д.","GET /сервисы/api/kn/commissioning?place=66&objStatus=0 → диапазон годов сдачи: {data:{minYear:2025, maxYear:2032}}","GET /сервисы/api/kn/metro?place=66&objStatus=0 → метро региона: {data:{list:[{id, name, line, color}]}}. Свердл.обл — Екатеринбургское метро ~9 станций","GET /сервисы/api/kn/hru/groups?place=66 → агрегированные фасеты с count: {data:{objClass:[{id,value}], status:[], type:[], wall:[], ...}}. Для UI левой колонки фильтров"]}
{"type":"entity","name":"DomRF_API_PortalAnalytics_Apr26","entityType":"api_spec","observations":["Группа A: /portal-analytics/api/* — без авторизации. Основной бэкенд аналитики.","Базовые справочники:","GET /portal-analytics/api/dictionaries/regions → 9 ФО, каждый с regions[]{id, name}","GET /portal-analytics/api/dictionaries/developers → 2734 девелоперов {id, name}, id-формат 'groupId_devId'","Dashboard endpoints (используются в Tab1, Tab4, Tab8):","GET /portal-analytics/api/dashboard/by-region?regionId=66 → массив 89 объектов на регион","GET /portal-analytics/api/dashboard/by-developer?regionId=66 → массив на застройщика (~750KB без регион-фильтра)","GET /portal-analytics/api/dashboard/by-room-count[?regionId=66] → агрегаты по комнатностям (ONE/TWO/THREE/FOUR)","GET /portal-analytics/api/dashboard/by-flat-area → 8 бакетов: FROM_0_TO_25, FROM_25_TO_35, ..., FROM_100_TO_INFINITY","Структура ответа dashboard/*: {id, flatCount, area, percent, details:[{roomCountType, flatCount, area, percent}]}","Расширенные endpoints (покрыты Tab2/Tab7/Tab9):","/launch/* — см. DomRF_Tab2_LaunchAndCommissioning_Apr26","/ready-construction/* — см. DomRF_Tab7_ReadyConstruction_Apr26","/building/* + /base/dictionaries/* + /comparison/regions — см. DomRF_Tab9_BuildingCommissioning_Apr26","/mortgage/* — см. DomRF_Tab11_MortgageStats_Apr26"]}
{"type":"entity","name":"DomRF_API_Files_Apr26","entityType":"api_spec","observations":["Группа D: файлы/картинки","GET /api/ext/file/{attachmentId}?type=png → скачать рендер ЖК или планировку квартиры","attachmentId берется из object.hobjRenderPhotoUrl (см. KnObject) или flat.image.attachmentId (см. KnFlats)","Формат файла обычно PNG, иногда JPEG. Для thumbnail используй attachmentIdSmall","Для GenDesign: можно скачивать ПЛАНИРОВКИ всех квартир с type='layout' — ~24K изображений по Свердл.обл для AI-обучения или показа аналогов"]}
{"type":"entity","name":"DomRF_API_Registries_Apr26","entityType":"api_spec","observations":["Группа F: Реестры (потенциальные доп. endpoints, не исследованы детально):","/сервисы/единый-реестр-застройщиков — реестр компаний с ОГРН/ИНН/КПП и историей","/сервисы/единый-реестр-мжк — реестр многоквартирных жилых комплексов","/сервисы/единый-реестр-жск — реестр жилищно-строительных кооперативов","/сервисы/единый-реестр-проблемных-объектов — проблемные ЖК для риск-фильтра","TODO: исследовать характерные endpoint-паттерны. Судя по структуре сайта каждый реестр имеет свой endpoint под /сервисы/api/* или /portal-kn/api/*"]}
{"type":"entity","name":"DomRF_Enums_Apr26","entityType":"api_spec","observations":["Справочные enum-ы из API ДОМ.РФ. При работе с endpoints используй именно эти коды.","regionId/regionCd: 66=Свердл.обл, 77=Москва, 50=МО, 78=Питер, 47=ЛО, 16=Татарстан, 23=Краснодар, 61=Ростов, 54=Новосибирск, 72=Тюмень, 2=Башкирия, 25=Приморье, 26=Ставрополь, 91=Крым, 59=Пермь, 36=Воронеж, 24=Красноярск, 27=Хабаровск, 71=Тула, 74=Челябинск, 63=Самара. Полный список: GET /portal-analytics/api/dictionaries/regions","objStatus: 0=строящийся в продаже, 1=сдан, 2=забронированы все или нет в продаже, 3=проблемный","flatStatus: free, booked, sold (через запятую как фильтр)","roomCountType: ONE, TWO, THREE, FOUR (для 4+)","objClass: 1=Типовой, 2=Комфорт, 3=Бизнес, 4=Элитный","wall (материал стен): 1=Блоки, 2=Кирпич, 3=Панель, 4=Монолит, 5=Монолит-кирпич","type (для квартир): 'Квартира-студия', '1-комнатная квартира', '2-комнатная квартира', '3-комнатная квартира', '4+комнатная квартира', 'Апартаменты'","mechanism (финансирование): 7=эскроу с проектным финансированием, 6=без эскроу старая схема, 5/4/3/2 = варианты ЖСК, кооперативов","energyEff: A++/A+/A/B/C/D — кодируется числами 6-9 (точное соответствие неизвестно, уточнить через UI labels)","calculationType (для /launch/*): SQUARE | HOUSES | FLATS","period: YEAR | MONTH"]}
{"type":"entity","name":"DomRF_OfficialAuth_Apr26","entityType":"api_spec","observations":["OAuth2 client credentials flow — единый механизм авторизации для всех 4 официальных спек (СЖС/НСИ/УОПО/АПФ).","Step 1: POST /idm-services/auth/realms/external-eisgs-idm/protocol/openid-connect/token","Body: grant_type=client_credentials&client_id={id}&client_secret={secret}","Headers: Content-Type: application/x-www-form-urlencoded","Step 2: Ответ = {access_token, expires_in: 300, refresh_expires_in: 1800, refresh_token, token_type: 'bearer', scope}","Step 3: Использовать `Authorization: Bearer {access_token}` во всех вызовах API","Token TTL: 300с (5 мин), refresh TTL: 1800с (30 мин). Max 20 одновременных сессий на Участника","Для АПФ дополнительный scope: fin-applications.readwrite.base","Режимы: Интеграционная среда (https://int.domrf.ru/) для тестирования, Промышленная (https://наш.дом.рф/) для боевого","Для Промышленной — IP-whitelist обязателен (IP регистрируются при подключении)","⚠ Доступно ТОЛЬКО внешним ИС официальных Участников ЕИСЖС (банки, Фонд, Госорганы). GenDesign НЕ имеет прямого доступа"]}
{"type":"entity","name":"DomRF_Spec_SJS_v130","entityType":"api_spec","observations":["API СЖС (Сведения о жилищном строительстве) v1.3.0 от 03.11.2020. Официальная B2B спецификация.","Base URL: https://наш.дом.рф/gw/sgs/api/v1/ (пром) | https://int.domrf.ru/gw/sgs/api/v1/ (инт)","Auth: OAuth2 + Bearer JWT (см. DomRF_OfficialAuth_Apr26)","Rate-limit: 400 запросов/24ч, 10/мин, page size max 50","30+ GET endpoints (все только READ):","/version, /model/current — служебные (XSD-схема)","/complexes, /complexes/{id}, /complexes/{id}/construction-objects — жилые комплексы","/construction-objects[?address&is_problem_object], /construction-objects/{id}, /{id}/extended, /{id}/documents, /{id}/files/{file-id}, /{id}/photos — объекты строительства","/developers, /developers/{id}, /{id}/extended, /{id}/complexes, /{id}/construction-objects, /{id}/documents, /{id}/files/{file-id} — застройщики","/company-groups, /company-groups/{id}, /{id}/developers, /{id}/complexes, /{id}/construction-objects — группы компаний","/problem-objects[?address], /problem-objects/{id} — проблемные объекты","История версий:","v1.0 (23.03.2020) — первая","v1.1.0 (29.05.2020) — добавлены /model/current, /{id}/files (старые /documents/files помечены deprecated)","v1.2.0 (07.09.2020) — добавлены /problem-objects + is_problem_object","v1.3.0 (03.11.2020) — добавлены query-параметры address и is_problem_object","С 2020 года новых версий не публиковали"]}
{"type":"entity","name":"DomRF_Spec_NSI_v101","entityType":"api_spec","observations":["API НСИ (Нормативно-справочная информация) v1.0.1 от 08.10.2020.","Base URL: https://наш.дом.рф/gw/rdm/api/v1/ | https://int.domrf.ru/gw/rdm/api/v1/","Auth: OAuth2 + Bearer JWT (см. DomRF_OfficialAuth_Apr26)","Rate-limit: 3000/24ч, 60/мин, page size max 1000 (самые либеральные из 4 спек)","15+ методов:","/refBook/{id}, /refBook/code/{refBookCode}, /refBook/version/{id}, /refBook/versions — справочники","/plainData/version/row/{rowId}, /plainData/version/{versionId}/data, /plainData/version/refBook/{refBookCode}/{date} — содержимое","/version/row/exists?rowId=, /version/structure?versionId=, /version/{versionId} — мета-инфо","/version/{versionId}/getFile, /getRawFile — выгрузка в XLSX/XML/JSON","/compare/getCommonComparableRows?oldVersionId=&newVersionId= — сравнение версий","Известные справочники: D024 (основания отказа 214-ФЗ), D025 (218-ФЗ). Для GenDesign почти не пригодится, разве что для маппинга кодов"]}
{"type":"entity","name":"DomRF_Spec_UOPO_v102","entityType":"api_spec","observations":["API УОПО (Уведомления об Отказах в Проведении Операций) v1.0.2 от 08.10.2020.","Base URL: https://наш.дом.рф/gw/mpo/api/v1/ | https://int.domrf.ru/gw/mpo/api/v1/","Auth: OAuth2 + Bearer JWT","Rate-limit: 300/24ч, 10/мин (только GET-методы)","Endpoints:","POST /prohibited-notifications — регистрация уведомления о запрещённой операции","GET /prohibited-notifications, /prohibited-notifications/{guid}, /{guid}/fond, /{guid}/non-profit — выборка и статус передачи","POST /misuse-notifications — уведомление о нецелевом использовании средств","GET /misuse-notifications, /{guid}, /{guid}/executive-authority, /{guid}/fond — выборка","Роли в матрице: УБ (уполномоченный банк), УБСЖС, Администратор","⚠ Доступ ТОЛЬКО для банков с эскроу-счетами (по 214-ФЗ ст.18.2 и 218-ФЗ ст.9.2-9.4). Для GenDesign бесполезен","Полезные для банка-партнёра в будущем (когда GenDesign интегрируется с Банк ДОМ.РФ/Сбер)"]}
{"type":"entity","name":"DomRF_Spec_APF_v22","entityType":"api_spec","observations":["API АПФ (Агрегатор Проектного Финансирования) v2.2 (2021).","Auth: OAuth2 + Bearer JWT, scope: fin-applications.readwrite.base","Rate-limit: не указан в спеке","Endpoints:","GET /project-financing/applications — список заявок на ПФ","GET /project-financing/applications/{guid} — полная анкета по заявке","PATCH /project-financing/applications/{guid} — подтверждение получения","GET /project-financing/files/{external-guid} — вложения","Анкета содержит 30+ объектов: financeRequest, questionnaire, financialIndicators, developerinfo, infoCompanyGroup, initialAndPermittingDocumentationForProject, landLegalRelations, projectCharacteristics, completedProjectsOutsideDeadline, financialReportCurrentYear, planingFinancialIndicators, projectBudget, requiredAmountFunding, infoGeneralContractor, generalContractorsLiabilitySRO, infoTechnicalCustomer, technicalCustomersLiabilitySRO, buildingPermit, expertiseDesignDocumentation, urbanPlanOfLand, landRightPurchase, objectCharacteristics, structureOfPlannedAreas, structureOfRealizedAreas, plannedInfrastructure, developerExperience, subjectRF, developerBenefiсiaries, mortgagedPropertyGuarantees, developerContactDetails, connectionToEngineeringNetworks, implementationOfProjects, debtAmounts","⚠ ОЧЕНЬ интересные данные для финмодели (нормативная стоимость, бюджет проекта, требуемое финансирование)","Но доступ ТОЛЬКО для банков-получателей заявок. Потенциальная цель партнёрства с банком на Раунд А","Структура респонса иллюстрирована в спеке в Приложении 1: schemeVersion='v2s01', subjectRF, projectAddress, isProjectDeclarationsPostedInEISZHS, projectDeclaration, characteristics + finance блоки"]}
{"type":"entity","name":"DomRF_OfficialVsFront_Comparison_Apr26","entityType":"api_spec","observations":["Главный вывод сравнения 4 официальных спек и фронт-API: ЭТО ДВА РАЗНЫХ ПРОДУКТА НА ОДНОМ ПОРТАЛЕ.","(а) Официальный B2B API ЕИСЖС /gw/{sgs|rdm|mpo|apf}/api/v1/* — OAuth2 + JWT, только для зарегистрированных банков-Участников","(б) Публичный фронт-API наш.дом.рф /portal-analytics/*, /portal-kn/*, /сервисы/api/kn/* — недокументированный, ключ Basic MTpqd2U= хардкоден в JS","СОВПАДАЮЩИЕ СУЩНОСТИ (во обоих API):","- Группа компаний, Застройщик, ЖК, Объект строительства, Проблемный объект","- Объект расширенные сведения: этажность, материал стен/перекрытий, отделка, класс, машиноместа, плановая дата ввода","- Списки документов (ПД, РНС, фотографии стр-ва)","ЧТО ЕСТЬ В ФРОНТ-API И НЕТ В СЖС:","⚠ PER-FLAT данные (24 441 квартир по Свердл.обл с priceChangeDate, pricePerSquareMeter, status free/booked/sold) — ЭКСКЛЮЗИВНО фронт!","⚠ priceChangeDate (velocity-tracking) — нет ни в одном официальном API","⚠ flats/map (bbox-поиск) — нет в спеке","⚠ flats/filters (UI sliders) — нет","⚠ Аналитические агрегаты (by-room-count, by-flat-area, by-region, by-developer) — нет как отдельных endpoints","⚠ launch / ready-construction / rpp / mortgage / escrow / project-finance — НИЧЕГО из этого нет в официальных спеках","⭐ ИТОГ: даже с B2B-доступом через банк-партнёр НЕЛЬЗЯ заменить публичный фронт для velocity-tracking + распределений. Реальный use-case GenDesign решается ТОЛЬКО через фронт-API","ЛИМИТЫ: СЖС 400 req/24h → выкачать все ЖК Свердл.обл (~283 ЖК × endpoints) НЕВОЗМОЖНО в официальном канале"]}
{"type":"entity","name":"DomRF_KeyAndLegal_Apr26","entityType":"feedback","observations":["Ключ Basic MTpqd2U= и юр. статус использования публичного фронт-API ДОМ.РФ.","Технически: сформирован из base64('1:qwe'). Хардкод в JS фронта. Бессрочен на момент проверки","В официальных спеках ЭТОГО КЛЮЧА НЕТ — спеки знают только Bearer JWT через OAuth2","Статус использования: ПАРСИНГ ПУБЛИЧНОГО ПОРТАЛА, НЕ ОФИЦИАЛЬНОЕ API","Why: ДОМ.РФ по 214-ФЗ обязан публиковать эти данные открыто — использование легально","How to apply: в реестре ПО декларируй формулировку 'интеграция с открытыми данными ЕИСЖС' или 'парсинг открытого портала наш.дом.рф'. НЕ используй формулировку 'API ДОМ.РФ' — зарезервировано за B2B-каналом СЖС/НСИ/УОПО/АПФ","Риск: фронт может отвалиться без предупреждения (ключ перевыпустят или поменяют URL)","Митигация: ежедневный smoke-test, fallback на /portal-analytics (no auth) для агрегатов","План B на блокировку фронта: партнёрство с банком-получателем СЖС API (Банк ДОМ.РФ, Сбер). Даёт SLA, но лимит 400/сутки и нет per-flat"]}
{"type":"entity","name":"DomRF_PerFlat_Schema_Apr26","entityType":"api_spec","observations":["Схема per-квартиры из GET /сервисы/api/kn/flats. 17 полей + вложенные объекты.","id (int) — глобальный ID квартиры в ЕИСЖС","odsId (string) — формат 'objId/sectionNum/flatNum' (напр. '64057/2/55'). Связь с реестром проектных деклараций","elemId (UUID) — токен для URL детальной страницы квартиры","type (string) — 'Квартира-студия' / '1-комнатная' / '2-комнатная' / '3-комнатная' / '4+комнатная' / 'Апартаменты'","number (string) — номер квартиры по застройщику","isStudio (bool)","totalArea (float) — общая площадь м² (продаётся)","livingArea (float) — жилая площадь м² (без коридоров/санузлов). Для финмодели важно отдельно","rooms (int) — кол-во комнат (студия = 1)","status (enum) — free / booked / sold","price (int) — полная цена в ₽","pricePerSquareMeter (int) — цена м² в ₽","priceChangeDate (string DD-MM-YYYY HH:MM) — дата последнего изменения цены. ⭐ КЛЮЧЕВОЕ ПОЛЕ для velocity-tracking","socialMortgage (bool) — доступна соц-ипотека","numberFloors (int) — этажность дома","floor (int) — этаж этой квартиры","image{attachmentId, attachmentIdSmall, hash, size, source, type} — при type='layout' рисунок планировки. Скачать: /api/ext/file/{attachmentId}?type=png","objInfo{hobjId, objTransferPlanDt, objReady100PercDt, objCommercNm, objAddr} — связь с ЖК","Разница objTransferPlanDt vs objReady100PercDt: плановая дата передачи квартир по ДДУ vs дата готовности дома. Лаг 3-6 мес важен для absorption analysis","Качество данных (проверка 26.04.2026): 'LIBERTY DOM' в ЛО — цены 2.6М и 2.7М ₽, площадь 22 и 23 м² — реалистично. priceChangeDate '30-11-2025' = 5 мес назад, значит плохо продаются"]}
{"type":"entity","name":"DomRF_PerFlat_VelocityTracker_Apr26","entityType":"research","observations":["Стратегия использования priceChangeDate + status из /сервисы/api/kn/flats для velocity-tracking в GenDesign.","Снимая snapshot раз в день мы видим:","1) Delta price — какие квартиры подешевели/подорожали","2) Status changes — какие перешли free→booked→sold","3) Velocity по ЖК — количество квартир сменивших status за период","4) Ценовая стратегия жков: активные priceChangeDate за 7 дней vs жки без движения цен месяцами","Это ровно то что нужно для Plan A ПЛИТКИ 3 (за какое время продастся):","— выводим absorption rate (квартир/мес) для ЖК-аналогов в радиусе 5 км","— проецируем на концепт пользователя","Альтернатива: можно использовать агрегированные endpoints DomRF_Tab6_Realization_Apr26 и DomRF_Tab7_ReadyConstruction_Apr26 — они дают те же sold% без выкачки всех 24K квартир. Первичный выбор — использовать их, per-flat оставить для deep-dive по радиусу"]}
{"type":"entity","name":"DomRF_PerFlat_ETL_Apr26","entityType":"research","observations":["ETL-стратегия и SQL-схема для per-квартиры из ДОМ.РФ в GenDesign Stage 2a.","Шаг 1: Daily full-refresh","Для каждого региона-таргета (66=Свердл, 50=МО, 77=Москва) → loop offset/limit с шагом 500 → upsert в dom_rf_flats","Шаг 2: Daily delta tracking","SQL diff dom_rf_flats vs dom_rf_flats_yesterday → вычислить (a) кто перешёл в sold, (b) кому изменилась цена, (c) кто новый. Запись в dom_rf_flat_events","Шаг 3: Materialized views — median(pricePerSquareMeter) по (region, type, year_quarter), absorption_rate по hobjId (sold quarters / 30 days)","SQL schema (PostgreSQL, Stage 2a):","CREATE TABLE dom_rf_flats (id BIGINT PRIMARY KEY, ods_id VARCHAR(50), elem_id VARCHAR(64), obj_id INT, hobj_id INT, type VARCHAR(50), number VARCHAR(20), is_studio BOOL, rooms SMALLINT, total_area NUMERIC(8,2), living_area NUMERIC(8,2), price NUMERIC(12,2), price_per_sqm NUMERIC(10,2), price_change_dt TIMESTAMPTZ, status VARCHAR(20), social_mortgage BOOL, floor SMALLINT, num_floors SMALLINT, layout_attachment_id VARCHAR(80), obj_commerc_nm TEXT, obj_addr TEXT, obj_transfer_plan_dt TIMESTAMPTZ, obj_ready_dt TIMESTAMPTZ, last_synced_at TIMESTAMPTZ, raw JSONB, region_cd SMALLINT)","Индексы: (region_cd), (hobj_id), (status), (type), (price_per_sqm), (price_change_dt). Для радиус-запросов нужен JOIN с dom_rf_objects по hobj_id чтобы получить geom","CREATE TABLE dom_rf_flat_events (flat_id BIGINT, event_dt TIMESTAMPTZ, event_type VARCHAR(20), old_value JSONB, new_value JSONB, PRIMARY KEY(flat_id, event_dt)) -- event_type: 'status_change' | 'price_change' | 'new_listing' | 'delisting'","Ожидаемый объём выкачки: Свердл.обл 24 441 квартир = 49 запросов при limit=500 = ~10 секунд при 5 RPS. МО+Москва — ~30 мин выкачки","Бонус — планировки: image.attachmentId с type='layout' = ~24K image по Свердл.обл. Можно скачать все для AI-обучения или показа аналогов"]}
{"type":"entity","name":"MCP_AddFacts_Preferred_Apr26","entityType":"feedback","observations":["Для всех записей в knowledge graph предпочтительны прямые вызовы MCP-инструментов (aim_memory_store / aim_memory_add_facts).","Why: прямые вызовы надёжнее python-скриптов, не требуют jsonl-обработки, поддерживают все фичи графа (связи, типы)","How to apply: используй python-скрипты только если MCP-сервер недоступен (fallback). Проверено 26.04.2026"]}
{"type":"entity","name":"DomRF_ExtractFlow_Objects_Apr26","entityType":"research","observations":["Двухшаговый flow для выгрузки всех ЖК региона из API ДОМ.РФ.","ШАГ 1: GET /portal-kn/api/sales/portal?flatStatus=free,booked&regions=66 → плоский массив objId всех ЖК в регионе (НЕТ авторизации)","ШАГ 2: для каждого objId: GET /сервисы/api/kn/object?objId={id} → полная карточка ЖК (см. DomRF_API_KnObject_Apr26)","Header для Шаг 2: Authorization: Basic MTpxd2U= (или MTpqd2U= — варианты видели в разных источниках, оба работают — проверить свежесть при deploy)","Ожидаемый объём: ~150-200 запросов на всю Свердл.обл. При rate-limit 5 RPS — 30-40 секунд на полный sync. ~3-5 мин на все Свердл+МО (~1000 ЖК)","Реальный пример (Екб, ЖК 'РАЗУМ на Малышева'):","objId=65136, devInn=3000007315, lat/lon=56.8346/60.6396","Метро Площадь 1905 года 27 мин","413 квартир, 19089 м²","Дата сдачи 2028-12-31","Средняя цена по ЖК 180828 ₽/м²","freeFlatsInfo.numberFlats = 52 (свободных на момент проверки)","⚠ КЛЮЧЕВАЯ ИНСАЙТНАЯ деталь: objPriceAVG — золотое поле для финмодели. priceMin часто означает 'студия 25 м²' — используй objPriceAVG","freeFlatsInfo.numberFlats — динамика в о времени = velocity proxy. Дельта суточных snapshots даёт кол-во проданных квартир без per-flat выкачки"]}
{"type":"entity","name":"DomRF_Object_ETL_Apr26","entityType":"research","observations":["ETL и SQL-схема для per-ЖК из ДОМ.РФ (отличается от per-flat в DomRF_PerFlat_ETL_Apr26).","Cron-task daily_dom_rf_sync:","Для каждого региона из списка целей → /sales/portal → массив objId → batch fetch /object → upsert в dom_rf_objects","Время на ~1000 ЖК — 3-5 мин. Кэш в Redis на 6ч","Cron-task daily_velocity_snapshot:","Пробежать те же objId, сохранить freeFlatsInfo.numberFlats с timestamp → dom_rf_velocity_snapshots (obj_id, snapshot_dt, free_count, price_min)","Из истории считаем absorption rate без выкачки per-flat","On-demand (Site Finder):","При запросе пользователя про участок → bbox 5км → /flats/map → топ-20 ЖК-аналогов → /object для каждого → median(objPriceAVG), median(objSquareLiving/objElemLivingCnt), avg(objReady100PercDt - objPublDt) для срока строительства","SQL Schema (PostgreSQL, Stage 2a):","table dom_rf_objects (obj_id PK, hobj_id, dev_id FK, dev_inn, group_name, region_cd, obj_addr, obj_short_addr, latitude, longitude, metro_id, metro_name, metro_time, obj_commerc_nm, obj_floor_min, obj_floor_max, obj_elem_living_cnt, obj_ready_100perc_dt, obj_square_living, obj_price_avg, obj_publ_dt, site_status, escrow_flg, problem_flg, building_type, ai_description, render_url, raw_payload jsonb, last_synced_at)","table dom_rf_developers (dev_id PK, dev_inn, short_name, full_name, group_name, company_group, org_form_id)","table dom_rf_velocity_snapshots (obj_id, snapshot_dt, free_count, price_min, PK(obj_id, snapshot_dt))","Индексы: GIST на (latitude, longitude) → ST_DWithin для радиус-запросов в районе","Связано с DomRF_PerFlat_ETL_Apr26 (там per-flat-схема dom_rf_flats + flat_events). Обе схемы нужны: объекты + квартиры"]}
{"type":"entity","name":"DomRF_BrokenEndpoints_Apr26","entityType":"api_spec","observations":["Endpoints ДОМ.РФ которые НЕ РАБОТАЮТ (проверка 26.04.2026). Не терять время на них.","GET /сервисы/api/kn/freeFlats?objId={id} → 502 (proxy error, путь возможно неверный)","GET /сервисы/api/kn/object/{id}/flats → 502","GET /portal-kn/api/object/{id} → 500 INTERNAL_ERROR","GET /portal-kn/api/object/{id}/flats → 500","Для per-flat данных (отдельные квартиры в ЖК) используй GET /сервисы/api/kn/flats?regions=X (см. DomRF_API_KnFlats_Apr26) — это рабочий endpoint","freeFlatsInfo.numberFlats в /object даёт только количество свободных, не детали"]}
{"type":"entity","name":"DomRF_Recon_Summary_Apr26","entityType":"research","observations":["Дата: 26.04.2026. Пассивный recon по публичным точкам ДОМ.РФ. Никаких active scans — только стандартные endpoints + headers от API-вызовов которые мы и так делаем.","9 отдельных находок сохранены рядом как DomRF_Recon_*_Apr26","Сильные находки: GitLab CI плейсхолдеры в accept-version, утечка feature-бранча+SHA, password grant_type в OIDC realm","Слабые находки (фингерпринты): X-Powered-By Undertow/Express, публичный sitemap, OPTIONS allow POST на read-only API","Для GenDesign это ИНВЕНТАРЬ рисков стабильности канала + потенциал для responsible disclosure","Active scans (DCR регистрация, password брут, IDOR, POST на /object) НЕ делали — требует scope-разрешения и BB-программы (которой у ДОМ.РФ нет)"]}
{"type":"entity","name":"DomRF_Recon_AcceptVersionLeak_Apr26","entityType":"research","observations":["Утечка #1 (основная): незакрытая шаблонная подстановка GitLab CI в response header.","На /сервисы/api/kn/* выдаётся: accept-version: ${env.CI_COMMIT_REF_NAME}_sha1:${env.CI_COMMIT_SHORT_SHA}#${env.CI_PIPELINE_ID}_20.04.2026 12:58:31","Переменные GitLab НЕ интерполируются на бэкенде — баг деплоя. Косвенное раскрытие: GitLab CI/CD они используют","Утечка #2: на /аналитика/api/escrow/* интерполированный accept-version: '3.9.0-new-memory-limits_sha1:a9723d46#2106101_05.08.2025 06:39:18'","Это раскрывает: (1) имя feature-бранча ('3.9.0-new-memory-limits'), (2) git SHA-1 коммита 'a9723d46', (3) GitLab pipeline ID '2106101', (4) дату деплоя 5.08.2025 — бэкенд escrow не обновлялся 8 месяцев","Риск: злоумышленник видит какие версии в проде + активные фичевые ветки = таргетинг known-CVE по библиотекам и enumeration internal feature flags","Severity: low-medium — инфо сама по себе не даёт эксплоит, но снижает работу река. Для responsible disclosure — кандидат #1"]}
{"type":"entity","name":"DomRF_Recon_OIDC_Apr26","entityType":"research","observations":["Публичный OIDC well-known: GET /idm-services/auth/realms/external-eisgs-idm/.well-known/openid-configuration","Стандартное раскрытие по RFC8414, но в этом случае раскрывает МНОГО внутренних модулей","scopes_supported — 50+ scope'ов = карта модулей системы:","lkfpc.developer.readwrite, lkfpc.ko.readwrite, lkfpc.bucket.read, lkfpc.developer-regfond.readwrite, lkfpc.technical.readwrite — ЛК ФПК (Фонд Развития Проблемных Компаний?)","erzkn.read.base — Единый Реестр Застройщиков, rpp.read.base — Реализация Продаж (наш Tab6!), mcalc.read.base — Mortgage Calculator","billing.files.readwrite.administrator, billing.files.readwrite.1c, billing.files.readwrite.services — billing-интеграция с 1С","smv.read.base, smvfs.read.base — СМЭВ и СМЭВ-ФС (система межведомственного электронного взаимодействия)","krp.read.base, fpp.read.base, rgp.read.base, sgs.str.read.base — внутренние модули","service_account, dictionary.export, profile.readwrite.base — админ-скоупы","Риск #1: grant_types_supported включает 'password' (Resource Owner Password Credentials) — устаревший grant, НЕ рекомендуется OAuth 2.0 BCP. Риск credential stuffing если есть пользовательские аккаунты","Риск #2: registration_endpoint = /clients-registrations/openid-connect — RFC7591 Dynamic Client Registration. Открытость НЕ проверялась (active scan)","Severity: medium — password grant + полная карта scopes помогают attacker'у навести прицел"]}
{"type":"entity","name":"DomRF_Recon_Stack_Apr26","entityType":"research","observations":["Три разных backend-стека за одним nginx-фронтом — раскрыто через X-Powered-By и accept-version.","/сервисы/api/kn/* → X-Powered-By: Undertow/1 (Стек Java/JBoss WildFly Undertow)","/api/document/* → X-Powered-By: Express (Node.js)","/portal-analytics/api/* → нет X-Powered-By, но accept-version выдаёт GitLab placeholders — явные признаки Spring Boot/Tomcat (Java)","/idm-services/auth/* → Keycloak (по ответам в OIDC well-known: realm 'external-eisgs-idm', issuer + пути 100% Keycloak)","Последствия для attacker: разные стеки = разные CVE-кандидаты. Последствия для GenDesign: время интеграции разное, лимиты разные, стабильность разная — нужны 3 отдельных smoke-теста по бэкендам","Severity: low — версии стандартных фреймворков публичны, но хорошая практика — убирать X-Powered-By"]}
{"type":"entity","name":"DomRF_Recon_RobotsTxt_Apr26","entityType":"research","observations":["GET /robots.txt — публичный, раскрывает схему API через Clean-param для Yandex.","Disallow строки: */auth/*, /api/ext/file/*.pdf, /files/*.pdf, /files/*?inline=1 — SEO-защита, не безопасность (файлы всё равно доступны)","Sitemap: https://наш.дом.рф/portal-sitemap/api/sitemap/root.xml","Clean-param выдаёт ПОЛНЫЙ список всех возможных query-параметров API (~80 имён):","objStatus, saleRoomFlg, metroId, time, walkFlg, companyGroupId, devId, fromDatePubl, toDatePubl, objTypeCd, objClass, fromQuarter, toQuarter, keyIssuance, escrowFlag, fundFlag, fromPrice, toPrice, checkFlg, objGreenHouseFlg, freePlan, nonLivFirstFloor, cargoPassElevFlg, parkingFlg, energyEff, wall, fromFloor, toFloor, maxLivingCnt, livElemEntrFloor, barrierTypes, landscaping, search, type, place, pdId, limit1000, sortDirection, sortName, flatStatus, bounds, rooms, page, limit, priceFrom, priceTo, sortField, sortType, areaFrom, areaTo, floorFrom, floorTo, pricePerSquareMeterFrom, pricePerSquareMeterTo, state, SaleType, residentialBuildings, ivElemEntrCnt, view, isBalconiesOrLoggias, activeSort, objectIds, isLivingFlg, regionHD, status, subject, region, problemReason, mechanism, dduFlg, transferFlg, searchValue, buildFlg, regionCd, devGroupId, regionActivity, repYear, calculationType, period, addrAreaId, devCalcGroupId, objClassCd, repMonth, devGroupValue, cityPopulation, inline, filename, cooperativeId","Риск: фактически документация API там где её не должно быть. Раскрывает несуществующие в UI параметры (regionHD, regionActivity, problemReason, fundFlag, checkFlg и др.) — это заявка на over-fetching","Severity: low-medium — помогает attacker'у искать скрытые фичи. Для нас — ПОЛЕЗНО для расширения набора фильтров в GenDesign клиенте"]}
{"type":"entity","name":"DomRF_Recon_OptionsPost_Apr26","entityType":"research","observations":["OPTIONS /сервисы/api/kn/object → Allow: HEAD, POST, GET, OPTIONS","POST разрешён на якобы READ-ONLY API — значит у них есть write-методы которые из публичной схемы не видны","Вероятно: для авторизованных юзеров через ЛК (личный кабинет) есть create/update operations на объекты","/portal-analytics/api/* в отличие — GET, HEAD, OPTIONS (read-only как положено)","Польза для нас (GenDesign): способ понять какие endpoints имеют write-поверхность — без активных тестов их","Риск (mass-assignment): если POST /object принимает JSON без валидации типов полей и имеет слабую auth — потенциальный вектор. НЕ ПРОВЕРЯЛИ (active scan)","Severity: неопределённая — зависит от реализации POST. Только факт раскрытия в OPTIONS — low"]}
{"type":"entity","name":"DomRF_Recon_CORS_Apr26","entityType":"research","observations":["CORS на /сервисы/api/kn/*:","Access-Control-Allow-Origin: <эхо Origin> (по видимому reflective)","Access-Control-Allow-Credentials: true","Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT","Access-Control-Allow-Headers: accept, authorization, content-type, x-requested-with","Access-Control-Max-Age: 1 (слишком мало — preflight каждый раз)","Риск: если Origin валидируется слабо (regex/null/эхо), злоумышленный сайт может дёргать API с сессией юзера. НЕ проверяли","Severity: low (обычно банки/фронт современных институтов валидируют жёстко). Но комбинация credentials:true + reflective Origin = классический misconfig","Полезно для нас (GenDesign): /сервисы/api/kn/* можно дёргать с любого Origin — не нужен прокси на нашем бэкенде (браузер пропустит прямые вызовы)"]}
{"type":"entity","name":"DomRF_Recon_PortalSitemap_Apr26","entityType":"research","observations":["Недокументированный service-prefix /portal-sitemap/api/ — раскрыт через robots.txt","GET /portal-sitemap/api/sitemap/root.xml → 200, 10 sub-sitemap'ов:","static.xml, turisticheskaya-nedvizhimost.xml, kvartiry-v-novostrojkah.xml, media.xml, edinyj-reestr-zhsk.xml, edinyj-reestr-zastrojshchikov.xml, gruppa-kompaniy.xml, object-zhsk.xml, katalog-novostroek.xml, proverka-novostroek.xml","GET /portal-sitemap/api → 404 (корневая ручка не работает — нужен конкретный sitemap)","GET /portal-sitemap/api/sitemap → 500 — ручка существует но багает без параметров","Для GenDesign: из sub-sitemap'ов можно вытащить ПОЛНЫЙ список URL всех ЖК/застройщиков/ГК/ЖСК в РФ — альтернатива двухшаговому flow через /sales/portal","Severity: инфо публичная (по robots.txt). 500 на /sitemap — легкий сигнал что в сервисе есть необработанный путь"]}
{"type":"entity","name":"DomRF_Recon_NoSourceMaps_Apr26","entityType":"research","observations":["ПРОВЕРКА: source maps для Next.js бандлов НЕ выложены (все *.js.map = 404).","main-*.js.map → 404, commons.*.js.map → 404, _app-*.js.map → 404, page chunks .map → 404","Это хорошая практика ДОМ.РФ — скрывают исходники React/TypeScript от выкладывания в prod","Но минифицированный JS всё равно реверсился — мы вывели все endpoints из него","Severity: нет (good practice)"]}
{"type":"entity","name":"DomRF_Recon_DisclosurePlan_Apr26","entityType":"feedback","observations":["План responsible disclosure если решим репортить находки ДОМ.РФ.","Why: у ДОМ.РФ НЕТ публичной BB-программы. Репортить нужно вручную без reward'ов, плюс риск вызвать подозрение и отзыв фронт-доступа (наш основной канал)","How to apply: отправить только если обваливается находка medium+. Из текущего списка: AcceptVersionLeak (medium), OIDC password grant (medium)","Канал: nash@domrf.ru (из их официальных контактов с /интеграция)","Альтернативный канал: CERT-GIB / НКЦКИ России если прямой репорт игнорируется","Шаблон репорта: описание находки → PoC (URL и response header) → impact → fix recommendation → время на fix (90 дней по обычаю). NDA не подписывать — данные и так публичные","ПРИОРИТЕТ ниже релиза GenDesign MVP — сначала делаем продукт, потом репорт. Но лучше репортить после начала партнёрства с банком-Раунда-А — будет легальный channel"]}
{"type":"entity","name":"DataSource_PerDeal_Reality_Apr26","entityType":"research","observations":["ПЛАН B для истинного per-deal: раздобыть данные Антона (ДДУ-канал) — см. блокировку #10 в PlanA_AnalyticsFirst_Apr25","ПЛАН C: партнёрство с банком (Сбер/ДОМ.РФ) для доступа к их внутренним ипотечным выдачам (это per-deal но только ипотечные, ~75% сделок)","ПЛАН D: ЕРЗ.РФ премиум-подписка — у них есть per-ЖК статистика продаж (по их рекламе), не проверяли. ~50-500 тыс ₽/год","⚠ ОБНОВЛЕНО 26.04.2026 вечер после находки Rosreestr open dataset:","ПРЕДЫДУЩИЙ ВЫВОД ОШИБОЧЕН — ПЕР-DEAL ДАННЫЕ ЕСТЬ. Росреестр стал публиковать CSV-выгрузки всех регистрируемых сделок с ЦЕНАМИ в рамках 'data-sety-rosreestra' (начали в 2024 или раньше).","СМ. DataSource_Rosreestr_DealsCSV_Apr26 — это теперь ОСНОВНОЙ источник per-deal данных","НОВАЯ ИЕРАРХИЯ источников:","1. ОСНОВНОЙ (фактические цены сделок, обе первичка+вторичка): Росреестр dataset_СДЕЛКИ (по кварталам в CSV)","2. ДОПОЛНИТЕЛЬНый (текущий прайс-лист + velocity, только первичка): ДОМ.РФ per-flat snapshot","3. CROSS-VALIDATION (ипотечные сделки): ЦБ РФ mortgage data","4. CROSS-VALIDATION (базовые рыночные цены): Fedstat 31452","5. REGION-SPECIFIC вторичка Екб: УПН (цены предложения)","ПЛАН B/C/D/E больше НЕ НУЖЕН — Росреестр CSV решает основную задачу. Партнёрство с банком или ЕРЗ — опциональное улучшение позже (для выявления ипотека/наличные и покупателя)"]}
{"type":"entity","name":"DataSource_CBR_Mortgage_Apr26","entityType":"research","observations":["ЦБ РФ ипотека: https://www.cbr.ru/statistics/bank_sector/mortgage/","Что есть (ТОЛЬКО АГРЕГАТЫ):","Жилищные кредиты физлицам (ОБЩИЙ объём, регион/банк/месяц)","Ипотечные кредиты + приобретённые права требования","Кредиты под залог ПРАВ ПО ДДУ (полезно: это прямой сигнал первичных продаж)","Досрочное погашение (квартальные)","Рефинансирование + эмиссия ЦБ","По регионам: объёмы выданных, задолженность (включая просроченную), кол-во кредитов, средневзвешенные сроки/ставки","Формат: XLSX, ~20+ таблиц (02_01..02_46+). Обновление ежемесячно по календарю","API НЕТ — только прямые ссылки на XLSX. ETL: cron-task раз в месяц скачать + распарсить","Для GenDesign: полезно для финмодели — региональные средние ставки, дают лучший сигнал чем выдачи от 1-2 банков","Это ДОПОЛНЯЕТ DomRF Tab10 (mortgage-rates: предложение) — ЦБ даёт фАКТИЧЕСКИЕ выдачи"]}
{"type":"entity","name":"DataSource_Fedstat_Apr26","entityType":"research","observations":["ЕМИСС / fedstat: https://www.fedstat.ru/. 8944 показателя от 60 ведомств, включая Росреестр и Росстат","Индикатор 31452 — 'Средняя цена 1 кв.м общей площади квартир на рынке жилья'","Разрезы 31452: квартал, регион (ОКАТО), рынок (первичка/вторичка), тип квартир (по кол-ву комнат). Данные 2000-2025. Обновление 09.02.2026 (19-23 рабочих дня после квартала)","Источник 31452: форма 1-РЖ 'Сведения об уровне цен на рынке жилья', Росстат","Формат: SDMX, XLSX. API видимо не публичный (search/start.do падает с 500 'isJpисключение')","Росреестр в fedstat: есть показатели по регистрациям, но их конкретные ID не определили (сервис поиска багает). TODO — разовая выгрузка вручную через браузер когда система работает","Для GenDesign: основное baseline для cross-validation цен в финмодели. Разовая выгрузка с обновлением раз в квартал"]}
{"type":"entity","name":"DataSource_Rosreestr_OpenService_Apr26","entityType":"research","observations":["Росреестр open-service: https://rosreestr.gov.ru/open-service/. Сайт отдаёт self-signed-cert в пробе (видимо gov-CA не в cert-store WebFetch — открывать вручную)","Что реально доступно (по предыдущим проверкам и публичным отчётам):","Публичная кадастровая карта (ПКК) — границы участков, кадастровый номер. НЕТ СДЕЛОК","Сведения ОГРН (о юрлицах регистрации) — реестры","Статистика в fedstat — АГРЕГАТЫ по регистрациям (кол-во ДДУ/установлений прав по регионам)","ПООБЪЕКТНЫХ ДДУ/КП НЕТ в открытых данных — это персональные данные по 152-ФЗ + коммерческая тайна","API: неформальный ДвОИЧНЫЙ https://pkk.rosreestr.ru/api/* (известно из community), используется в РосРеестр SDK","Для GenDesign: ПКК полезна для Site Finder (границы участка, КН, вид разрешённого использования). Для per-deal — бесполезен, только агрегаты через fedstat"]}
{"type":"entity","name":"DataSource_UPN_Ekb_Apr26","entityType":"research","observations":["Уральская Палата Недвижимости (Екб/Свердл.обл): https://upn.ru/","Аналитика на https://old.upn.ru/analytics.htm","Что публикуется (АГРЕГАТЫ):","Еженедельные отчёты 'Средние цены предложения недвижимости'","Территориальные разрезы: 4 района Екатеринбурга + Свердл.область","Архив: с 2007 года по настоящий момент (это 19+ лет longitudinal data!)","Формат: веб-страницы/PDF по годам и месяцам, без API. ETL = парсинг PDF + HTML","API/подписка: НЕ ОПИСАНО публично. Для коммерческого доступа — +7 343 367-67-60","ОГРАНИЧЕНИЕ: цены ПРЕДЛОЖЕНИЯ, НЕ сделок. Источник — листинги риелторов-членов УПН","Для GenDesign: ОТЛИЧНЫЙ region-specific baseline для Екатеринбурга. 19-летний ряд даёт хороший сигнал по истории рынка. Парсить раз в неделю","ПОТЕНЦИАЛЬНОЕ ПАРТНЕРСТВО: Екатеринбург-фокус у GenDesign + локальный бренд УПН = имеет смысл договориться о подписке на сделки (у риелторов уже есть фактические сделки)"]}
{"type":"entity","name":"DataSource_DomRFAsPerDeal_Apr26","entityType":"research","observations":["ДОМ.РФ как SYNTHETIC per-deal источник — самый жизнеспособный вариант для GenDesign без партнёрств.","Принцип: ежедневный snapshot /сервисы/api/kn/flats?regions=66 → diff с вчерашним → события","События которые мы получим (каждое = synthetic deal):","(a) status_change: free → booked = бронь, free → sold = прямая продажа, booked → sold = выкуп после брони","(b) price_change: priceChangeDate поменялась → (возможно продажа и передобавление, или ревальвация)","(c) delisting: квартиры нет в списке → продали (sold или сделали невидимой)","(d) new_listing: новая квартира = новый старт продаж","Результат: таблица dom_rf_flat_events (см. DomRF_PerFlat_ETL_Apr26) с полями (flat_id, event_dt, event_type, old_value, new_value)","ОГРАНИЧЕНИЯ: (1) НЕТ инфы о покупателе (физ/юр лицо, ипотека/нал), (2) НЕТ инфы о фактической цене сделки (может быть дискаунт вне прайс-листа), (3) ~3-7 дней лаг между сделкой и обновлением статуса в ЕИСЖС","ДЛЯ GenDesign: этого ДОСТАТОЧНО для Plan A 'ПЛИТКИ 3' (за какое время продастся). Абсолютная точность цены не нужна — нужен тренд/velocity"]}
{"type":"entity","name":"DataSource_Rosreestr_DealsCSV_Apr26","entityType":"research","observations":["Дата: 26.04.2026. ГЛАВНАЯ НАХОДКА: Росреестр СДЕЛАЛ ПУБЛИЧНЫМИ регистрируемые сделки с недвижимостью (CSV-выгрузки по кварталам).","URL: https://rosreestr.gov.ru/data-sets/ — Apache open directory listing","Описание: https://rosreestr.gov.ru/open-service/data-sety-rosreestra/dannye-o-tsenakh-registriruemykh-sdelok-po-otchuzhdeniyu-s-obektami-nedvizhimosti-v-razreze-territorialnoy-prinadlezhnosti/","Структура директории:","/data-sets/{N квартал YYYYг.}/dataset_СДЕЛКИ_r-r_01-92_y_YYYY_q_N.csv.zip","/data-sets/{N квартал YYYYг.}/dataset_КАДАСТРСТОИМОСТЬ_r-r_{XX-YY}_y_YYYY_q_N.csv.zip (4 файла по регионам)","/data-sets/{N квартал YYYYг.}/dataset_АРЕНДА_r-r_01-92_y_YYYY_q_N.csv.zip","Доступные периоды: все 4 квартала 2024, все 4 квартала 2025, 1 кв 2026 (обновлен 16.04.2026). + Архив до 2023г. включительно (отдельный пакет)","Частота: ежеквартально (публикуется ~через 1.5 месяца после окончания квартала)","Q1 2026 факты: dataset_СДЕЛКИ_*.csv.zip = 9.5 MB ZIP, 96 MB CSV, 569 723 строки","Подсчёт по Q1 2026: 898 302 сделки по РФ всего (709 812 ДКП + 188 490 ДДУ). Свердл.обл: 37 310 сделок","Источник: ФГИС ЕГРН — реальные зарегистрированные сделки (не листинги, не предложения)","Исключения: безвозмездные сделки НЕ включены (дарения, наследования)"]}
{"type":"entity","name":"DataSource_Rosreestr_DealsCSV_Schema_Apr26","entityType":"api_spec","observations":["Схема CSV-выгрузки Росреестра dataset_СДЕЛКИ. Кодировка: UTF-8. Разделитель: '~' (тильда!). 17 полей:","number — КОЛИЧЕСТВО сделок в этом ряду (ряд = агрегация одинаковых сделок). Для расчёта итогов НАДО умножать на number","okato — ОКАТО код","region_code — ID региона (66=Свердл.обл, 77=Москва, ...)","district — муниципальный район/округ","city — населённый пункт","quarter_cad_number — КАДАСТРОВЫЙ КВАРТАЛ (напр. '50:12:0010209'). Это самый важный гео-ключ — блок размером от дома до квартала. Можно джойнить с ПКК Rosreestr","street — улица (часто пустая)","realestate_type_code — тип объекта: 002001001000=ЗУ, 002001002000=Здание, 002001003000=Помещение, 002001009000=Машиноместо","wall_material_code — СПРАВОЧНИК 126_УНСИ_Перечень наименований материалов наружных стен","year_build — год постройки/ввода в эксплуатацию","floor — этажность (для Здания) / номер этажа (для Помещения)","purpose_code — назначение объекта: спр 66_УНСИ (Здания), 67_УНСИ (Помещения), 148_УНСИ (виды разрешённого использования ЗУ)","area — площадь (м² для помещений, м² для ЗУ)","period_start_date — ПЕРВОЕ ЧИСЛО КВАРТАЛА. ⚠ НЕ фактическая дата сделки — все сделки квартала имеют одну и ту же дату. Гранулярность времени = квартал","deal_price — ЦЕНА СДЕЛКИ в валюте (средняя если number>1)","currency — 'рубль' в большинстве случаев","doc_type — 'ДКП' (договор купли-продажи, вторичка и ГП) или 'ДДУ' (долевое строительство — ПЕРВИЧКА)","ГРАНУЛЯРНОСТЬ итоговая: row = уникальный (регион, район, нас.пункт, кад.квартал, улица, тип, материал, год, этаж, назначение, площадь, doc_type) + ЦЕНА + number. Для квартир это близко к per-flat (но без номера квартиры и конкретной даты)"]}
{"type":"entity","name":"DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026","entityType":"research","observations":["Реальные цифры из скачанного dataset_СДЕЛКИ за Q1 2026 по Свердл.обл (region_code=66) — проверка качества источника.","ИТОГО сделок в Свердл.обл за Q1 2026: 37 310 (после умножения на number)","Распределение по типу объекта:","Помещения (квартиры/нежилые): 24 923","Земельные участки: 7 157","Здания: 3 130","Машиноместа: 2 100","Распределение по doc_type:","ДКП (вторичка+ГП): 26 655","ДДУ (ПЕРВИЧКА): 10 655","Практически все ДДУ = новостройки + прямая покупка от застройщика. ДКП — вторичка и прямые П в ГП","ЦЕНЫ ₽/м² ПО ПОМЕЩЕНИЯМ (выборка: area 5-500 м², price>100К):","ДКП median: 82 594 ₽/м², mean: 89 206 ₽/м² (n=14 994)","ДДУ median: 156 314 ₽/м², mean: 220 983 ₽/м² (n=664)","Первичка ВДВОЕ дороже вторички в Свердл.обл — логично (вторичка включает хрущёвки 60-х годов, НП, МО подмосковье и т.д.)","Сверка с baseline: статистика ДОМ.РФ / Росстат по Свердл.обл в ~85-95 тыс ₽/м² (Apr 2025) — совпадает с ДКП median 82,594","ПРИМЕРЫ реальных сделок в Екб (квартал 66:41:*):","4.8М ₽ за 40.9 м² (117К ₽/м²), дом 2019, 3 этаж","6.7М ₽ за 32.2 м² (208К ₽/м²), дом 2022, 6 этаж","1.9М ₽ за 28.9 м² (66К ₽/м²), дом 1962 — хрущёвка","ТОП районы: 'Екатеринбург' (1642+1293=2935), Сысертский (1098), Белоярский (728)","Для GenDesign ПЛИТКИ 2 (ЦЕНА): рабочая выборка — сделки ПОМЕЩЕНИЙ в кадастровых кварталах в радиусе 5км от участка пользователя, раздельно ДКП vs ДДУ"]}
{"type":"entity","name":"DataSource_Rosreestr_ETL_Plan_Apr26","entityType":"research","observations":["ETL-план интеграции открытых данных Росреестра в GenDesign Stage 2a.","ИСТОЧНИКИ: 3 dataset типа на квартал: СДЕЛКИ (НАШ!), АРЕНДА, КАДАСТРСТОИМОСТЬ (4 файла)","ОБЪЁМ СДЕЛОК по кварталу: ZIP 9-30 MB, CSV 96-300 MB, ~600К-1.5М строк","ДОСТУПНО НА СЕЙЧАС: 9 кварталов (Q1 2024 - Q1 2026) + Архив до 2023г. (JSON-выгрузки по регионам, ~50-300 MB на регион в ZIP)","СТРАТЕГИЯ заливки:","Шаг 1: bootstrap — одноразовый скрипт скачивает все 9 кварталов СДЕЛОК → распакует → фильтрует region_code IN (66, 50, 77) → upsert в PostgreSQL","Шаг 2: cron-task quarterly_rosreestr_sync — раз в квартал (16-е число второго месяца после окончания квартала) проверять index и тянуть новый квартал","Шаг 3: обогащение: JOIN с ПКК Rosreestr по quarter_cad_number → получить geom квартала (полигон) + центроид","SQL Schema (PostgreSQL):","CREATE TABLE rosreestr_deals (id BIGSERIAL PK, region_code SMALLINT, district TEXT, city TEXT, quarter_cad_number VARCHAR(30), street TEXT, realestate_type_code VARCHAR(15), wall_material_code VARCHAR(15), year_build SMALLINT, floor TEXT, purpose_code VARCHAR(15), area NUMERIC(12,2), period_start_date DATE, deal_price NUMERIC(14,2), currency VARCHAR(10), doc_type VARCHAR(10), deal_count INT, raw_okato VARCHAR(15), source_quarter VARCHAR(10))","Индексы: (region_code), (quarter_cad_number), (period_start_date), (doc_type), (realestate_type_code), GIST на geom после энричмента","Materialized views: median(price/area) по (region, quarter, doc_type, realestate_type) и по радиусу 5км вокруг lat/lon","Объём работы: скачать+распаковать+лоаднуть 9 кварталов в PG для 3 регионов = 2-3 часа. ETL код = 4-6 часов. ПКК-энричмент = 1-2 дня","Для ПЛИТКИ 2 в GenDesign: это ОСНОВНОЙ источник фактических цен сделок (ДОМ.РФ остаётся для текущего прайс-листа и velocity)"]}
{"type":"entity","name":"DataSource_Rosreestr_DealsCSV_Limits_Apr26","entityType":"research","observations":["ОГРАНИЧЕНИЯ открытого dataset Росреестра dataset_СДЕЛКИ — важно знать перед интеграцией.","1. НЕТ покупателя/продавца — персональные данные по 152-ФЗ НЕ выкладываются","2. НЕТ конкретной даты сделки — period_start_date = первое число квартала. Гранулярность времени = 90 дней","3. НЕТ кадастрового номера ОБЪЕКТА, только КАДАСТРОВЫЙ КВАРТАЛ. Нельзя связать с ДОМ.РФ odsId/elemId напрямую","4. ГРУППИРОВКА дубликатов в row + number: если 5 одинаковых квартир в одном жк проданы с похожими характеристиками — склеиваются в 1 ряд с number=5 и СРЕДНЕЙ ценой","5. НЕТ инфы о форме оплаты (наличные/ипотека), только итоговая цена","6. НЕТ комнатности квартиры. Можно инферить по площади (>50м² = 2к, >70 = 3к, ...) но не точно","7. НЕТ застройщика/ЖК в явном виде — выводим через JOIN ПКК → ДОМ.РФ /object по координатам квартала","8. Безвозмездные сделки (дарения, наследства) НЕ включены","9. ЛАГ: dataset публикуется ~через 1.5 месяца после конца квартала (Q1 2026 вышел 16.04.2026)","10. САМОСТОЯТЕЛЬНОСТЬ от ДОМ.РФ: СДЕЛКИ регистрируются все (и вторичка и первичка), тогда как ДОМ.РФ покрывает только первичку в строящихся ДОМАх = Росреестр ШИРЕ","11. ЮР.СТАТУС: официальный open data, в реестр ПО декларируем 'Интеграция с открытыми данными Росреестра (фИГС ЕГРН)' — легально и без NDA"]}
{"type":"entity","name":"Rosreestr_SiteMap_Apr26","entityType":"research","observations":["Карта ресурсов Росреестра (обзор 26.04.2026 passive recon).","rosreestr.gov.ru — ОСНОВНОЙ портал (Bitrix CMS), TLS с self-signed-cert (Минцифры CA, не в system store)"," ├─ /eservices/ — электронные услуги (выписки ЕГРН 340-4160 ₽, регистрация прав, ДДУ-проверка)"," ├─ /opendata/ — 17 МАНДАТНЫХ open data наборов (СРО кадастровых инженеров, лицензии, проверки, ГКГН). Базовые реестры без сделок"," ├─ /open-service/data-sety-rosreestra/ — ⭐ 3 ДАТАСЕТА с РЫНОЧНЫМИ ДАННЫМИ:"," │ ├─ СДЕЛКИ (ДКП+ДДУ) с ценами — см. DataSource_Rosreestr_DealsCSV_Apr26"," │ ├─ КАДАСТРСТОИМОСТЬ (4 файла по регионам)"," │ └─ АРЕНДА (договоры аренды)"," ├─ /data-sets/ — Apache OpenIndex файлы CSV по кварталам — см. DataSource_Rosreestr_DealsCSV_Apr26"," └─ /open-service/statistika-i-analitika/ — только пресс-материалы, нет выгрузок","nspd.gov.ru — НОВЫЙ ПОРТАЛ НСПД (Национальная Система Пространственных Данных), заменил ПКК"," ├─ React SPA с Module Federation (микро-фронты)"," ├─ /api/{service-name}/{version} — микросервисы: notifications-controller/v2, ticket-support/v3, registers-manager/v2, tech-process/v2"," ├─ Все API требуют auth — ESIA через Госуслуги"," └─ X-TIMEZONE header обязателен","pkk.rosreestr.ru — 301 → nspd.gov.ru/map?thematic=PKK (старый ПКК устарел)","lk.rosreestr.ru — Личный кабинет (React SPA, ESIA auth)","rosreestr.ru — старый домен (большинство поддоменов не отвечают в пробе)"]}
{"type":"entity","name":"Rosreestr_OpenData_17Sets_Apr26","entityType":"research","observations":["Полный список 17 open data наборов на https://rosreestr.gov.ru/opendata/ (ПО идентификатору 7706560536 = ИНН Росреестра).","Наборы реестров СРО (полезные GenDesign):","1. СРО кадастровых инженеров — контрагенты для топосъёмки","2. СРО оценщиков — профессиональная оценка для финмодели","3. СРО арбитражных управляющих — для проблемных объектов (банкротство застройщиков)","4. Реестр лицензий на геодезическую и картографическую деятельность","5. Государственный каталог географических названий — полезно для нормализации адресов","Наборы НЕ полезные для GenDesign:","6-9. Планы/результаты проверок (землепользование, геодезия, СРО)","10. Перечень ГИС Росреестра","11-13. СРО медиаторов, РОК, СРО без полномочий, ЭП-площадок","14-17. Различные проверки и результаты","Это ГОС-МАНДАТ по 8-ФЗ 'O доступе к информации'. Реальные рыночные данные (СДЕЛКИ/КАДАСТР/АРЕНДА) НЕ здесь, а в отдельном блоке /open-service/data-sety-rosreestra/","Формат выгрузки (по паспорту): CSV/XML/JSON раз в квартал/месяц в зависимости от набора"]}
{"type":"entity","name":"NSPD_Architecture_Apr26","entityType":"api_spec","observations":["НСПД (nspd.gov.ru) — новый портал Росреестра для пространственных данных, заменил ПКК (pkk.rosreestr.ru → 301)","Архитектура:","— React SPA с Vite билдом (видно по import-паттернам и vite_API_BASE)","— Module Federation с micro-frontends (видны runtime hooks @nspd-modules/*)","— Effector + atomic-router для state management","— ui kit @nspd/uikit (внутренний)","— Map: @nspd-modules/map-core, map-adapter","— Yandex Metrika (yandex-metrika-xOrTB1Q0.js)","— Special browser support: YaBrowser, Firefox, Chromium-Gost, Chrome (без Edge)","Microservices API base = '/api/{service}/{version}':","— /api/notifications-controller/v2/notifications","— /api/ticket-support/v3/tickets","— /api/registers-manager/v2 — реестры","— /api/tech-process/v2 — техпроцессы","— /api/aeggis-portal/v3/spatial-data-info — инфо пространственные данные (AEGGIS = Application for Earth Geospatial Information System)","— /api/aeggis-portal/v1/auth-providers — провайдеры авторизации","— /api/services — сервисы НСПД","Все вызывают 403 без auth (видимо SSO через Госуслуги/ESIA)","Обязательный header: X-TIMEZONE","Для GenDesign: НСПД не даёт прямого API без ESIA-входа. Альтернатива — старый ПКК-API community библиотек (rosreestr2coord) они могли сломаться после миграции"]}
{"type":"entity","name":"Rosreestr_Recon_Findings_Apr26","entityType":"research","observations":["Passive recon наблюдения на rosreestr.gov.ru и nspd.gov.ru (26.04.2026). Только то что видно при просмотре публичных страниц и их bundle. Без active scan.","1. ⚠ dev-поддомен в prod-bundle (medium): в nspd.gov.ru/assets/api-ByMDT02-.js вывернута vite переменная VITE_PROXY_DOMAIN=https://dev.nspd.rosreestr.gov.ru — раскрывает существование dev-копии портала. Прямые пробы dev-хоста НЕ делали (active recon за рамками пользовательского запроса)","2. ⚠ X-Powered-CMS header (low): rosreestr.gov.ru отдаёт 'X-Powered-CMS: Bitrix Site Manager (d61e85ea0be7ddfb3fa5a12935cc91a6)' — раскрывает CMS + license-hash. Обычно хеш = SHA Bitrix лицензии (в отличие от просто 'Bitrix') — портрет продакшн инстанса","3. ⚠ Двойной Referrer-Policy header (low): выдаются два разных 'Referrer-Policy: origin-when-cross-origin' и 'Referrer-Policy: unsafe-url'. По спеке второй выигрывает — unsafe-url пропускает ПОЛНЫЙ URL+query в Referer на внешние сайты. Утечка приватности","4. ⚠ SameSite отсутствует в cookies (low): PHPSESSID, USER_REGION_ID, USER_CITY выдаются без SameSite-атрибута. CSRF risk при входе в ЛК","5. ⚠ P3P header устарел (info): policyref='/bitrix/p3p.xml' — P3P стандарт давно обсолетен (W3C прекратил в 2009)","6. ⚠ Typo в canonical URL (cosmetic): на nspd.gov.ru в <link rel=canonical> указан 'nspd.rosreetr.gov.ru' (rosreetr без 's') — опечатка в build","7. ⚠ Отсутствует Content-Security-Policy header на обоих доменах (low) — слабая защита от XSS","8. ⚠ robots.txt разрешает /opendata/ но НЕ учитывает /open-service/data-sety-rosreestra/ и /data-sets/ — это не баг, это отсутствие стратегии (файлы индексируются)","9. Открытая директория /data-sets/ (info, НЕ уязвимость, это полезный listing) — Apache mod_autoindex. Но кодировка имён в листинге = cp1251 (mojibake в UTF-8 браузере), свидетельство legacy Apache config","10. SSL TLS с российским CA (Russian Trusted CA / Минцифры) — не в trust store обычных OS/браузеров. Браузер Chromium-Gost или ruchnoe доверие в system store нужны. Для ETL в GenDesign — curl -k или ручное включение CA","Severity общая: все наблюдения LOW-MEDIUM. Ничего критичного не найдено (и не искали active scan'ами)","ДЛЯ GenDesign: из утечек ничего не используем. На реестр ПО декларируем только легальные источники: 'open data Rosreestr' (data-sety-rosreestra)"]}
{"type":"entity","name":"Rosreestr_TLS_Note_Apr26","entityType":"feedback","observations":["Росреестр (rosreestr.gov.ru, nspd.gov.ru) использует TLS-сертификат от российского CA (Russian Trusted CA Минцифры), который НЕ включен в браузеры/OS из коробки за пределами РФ.","Why: после санкций 2022 российские госресурсы перевели выдачу TLS на Минцифры. Обычный Chrome показывает ERR_CERT_AUTHORITY_INVALID","How to apply в GenDesign:","1) При ETL/curl используй флаг -k (skip cert check) — это безопасно потому что это открытые данные без auth/PII","2) Для строгой валидации в проде — добавь в trust store: https://www.gosuslugi.ru/crt/MinCifry_RootCA.pem","3) Python requests: используй verify=False или verify=path_to_minciftry_ca","4) Браузеры: Yandex Browser и Chromium-Gost включают CA по умолчанию","Не связано с security: это инфраструктурная особенность. Наблюдаемые данные в открытом доступе легальны"]}
{"type":"entity","name":"NSPD_OAuth_Architecture_Apr26","entityType":"api_spec","observations":["NSPD (nspd.gov.ru) auth: собственный OAuth2/OIDC сервер на sso.nspd.gov.ru, провайдер = ESIA Госуслуги.","Token endpoint: POST https://nspd.gov.ru/oauth2/token (прокси на sso.nspd.gov.ru)","Body: {grant_type: 'refresh_token'|'authorization_code', client_id: 'nspd'} — как JSON, NOT form-urlencoded","Real client_id (UUID): 03386dbe-5185-4b96-900d-c2b1bb368ed6","JWT issuer: https://sso.nspd.gov.ru, algo: RS256","JWT TTL: 1800с (30 мин). Refresh ttl: лонже (30+ мин, точно не известно — не проверяли)","Cookie storage: authAccessToken + authRefreshToken в cookie с HttpOnly, secure, SameSite=None, domain=nspd.gov.ru. Недоступны JS, но видны в DevTools Network","ESIA scope (при входе запрашивается): ОРГАНИЗАЦИИ, АДРЕСА, ДР, фИО, ИНН, СНИЛС, емаил, телефон, ПАСПОРТ — очень широко для сервиса карты. Для GenDesign это предупреждение же — НЕ интегрируем НСПД с ESIA в наш продукт (слишком большой PII surface)","JWT claims (PII!): aud, client_id, display_name, email, family_name, given_name, middle_name, sub (UUID), uid (UUID), preferred_username, sid, scope='profile email uid', updated_at","X-TIMEZONE обязателен в каждом запросе","Backend сигнатура: x-backend: dc1-gw-8-1, x-api-header: af, x-request-id: hex"]}
{"type":"entity","name":"NSPD_PhysicAccess_Apr26","entityType":"research","observations":["Доступ к NSPD API для physic-аккаунта (физлицо через ESIA) — проверено эмпирически 26.04.2026.","GET /api/registers-manager/v2/pages/main → 200, typeAccount: 'physic', 18 сервисов:","approvalInConstruction (согласования в строительстве), integratedDevelopmentOfTheTerritory (КРТ), individualHousingConstruction (ИЖС), myProperties (мои объекты), arcticPeopleLanguages, urbanPlanningStudyOnline (градопроработка), smallBusiness, assistantSurveyor (помощник изыскателя), geodataVisualization, cadastralValuation, landNspd, farmLand, buildingLand, tourismNspd, marketAnalytics (НАШ!), complexCadastralWorks, specialTools, thematicUserLayers","URL-маппинг сервисов (frontend routes):","/market-analysis → marketAnalytics","/urban-analyze → urbanPlanningStudyOnline","/construction-nspd → buildingLand (земля для стройки)","/integrated-development-territories → КРТ","/cadastral-valuation → cadastralValuation","/my-properties → myProperties","/assistant-surveyor → assistantSurveyor","GET /api/notifications-controller/v2/notifications → 200 (totalCount: 0 для нового юзера)","GET /api/portal-tools/v1/page-assistant/{pageCode} → 200 (флаг assistant)","POST /api/portal-tools/v1/audit → 200 (аудит пользовательских действий)","ЗАКРЫТО для physic (403 Forbidden код=3):","/api/registers-manager/v2/registers/can-get-tree — дерево реестров","/api/aeggis-portal/v3/* — портал пространственных данных (объекты, registry-list, spatial-data-info, auth-providers)","/api/services/* — сервисы NSPD","/api/v1/parcels — парцели","Эти endpoints видимо для organisation-аккаунта (юрлицо) или госслужащих","Для GenDesign: physic-аккаунта хватит для marketAnalytics + WMTS-карта. Реестры/объекты — требуют юрлица"]}
{"type":"entity","name":"NSPD_MarketAnalytics_API_Apr26","entityType":"api_spec","observations":["Сервис nspd.gov.ru/market-analysis — 'Аналитика рынка недвижимости', официальный сервис Росреестра.","Источник данных: Цены сделок по продаже квартир на вторичном рынке из ФГИС ЕГРН с 2018 года","Разрезы: федокруг / субъект РФ / населённый пункт / кадастровый квартал. Визуализация: тепловая карта, графики, таблица","Auth: ESIA-вход (physic), JWT в cookie","Base: /api/market-analytics/v1/","GET /filters/indicators → [{id:1,title:'Индикатор цен ежемесячный',type:M},{2,'Квартальный',Q},{3,'Полугодовой',H},{4,'Годовой',Y}]","GET /filters/calculationMethod → [К базисному, К предыдущему, К аналогичному периоду годом ранее]","GET /filters/dataSource → [{1,ФГИС ЕГРН,fgisEgrn},{2,Внешние,externalSource}]","GET /filters/areaRanges → [0-25, 25-40, 40-60, 60-80, 80-100, 100+]","GET /federal-district → [8 ФО с codes 1-8]. Уральский=6, Сибирский=7, Дальневосточный=8, Приволжский=5, СКФО=4, СЗФО=2, ЦФО=1, ЮФО=3","GET /groups/fgisEgrn → полная схема фильтров: dataSource, indicators, calculationMethod, periodFrom/periodTo, federalDistrict, federalSubject, settlement, cadastralQuarter, areaRanges. limit=10 на множественные выборы","GET /layers-tree → 6 MVT-слоёв на разные площади. layerId 872964-872969. categoryId 470043. visualType=bubble, minZoom=2, tileExtent=512","POST /period (body: {type, dataSourceSysName}) — периоды доступные для индикатора (POST, валидации проверены)","POST /settlement (body: другой формат — не выявлен) — нас.пункты","GET /federal-subject?federalDistrict={code} — видимо есть но ожидает другой формат параметров","Data endpoint (чарт/таблица) — НЕ НАЙДЕН без реального UI-выбора. Связаные endpoints для рендера в SPA ловятся только при полном set выборе фильтров","КОНЦЕПЦИЯ для GenDesign: это ГОТОВЫЙ official aggregation API по сделкам ПО КАДАСТРОВЫМ КВАРТАЛАМ. В отличие от CSV-датасета (сырые сделки раз в квартал) — это предварительно вычисленные индикаторы с выбором временного окна (M/Q/H/Y) и динамики относительно базы/предыдущего/ГОГ"]}
{"type":"entity","name":"NSPD_AEGGIS_WMTS_Apr26","entityType":"api_spec","observations":["AEGGIS WMTS API НСПД — картирование слоёв в стандарте OGC WMTS.","GET /api/aeggis/v4/{layerId}/wmts/{z}/{x}/{y}.png — PNG растровые тайлы. layerId=235 — 'Цифровая объектовая схема' (базовый справочный слой)","GET /api/aeggis/v4/{layerId}/mvt/{z}/{x}/{y} — Mapbox Vector Tiles (предположение по schema layers-tree)","MarketAnalytics MVT-слои: 872964 (объекты 0-25м²), 872965 (25-40), 872966 (40-60), 872967 (80-100), 872968 (100+), 872969 (60-80). Все из categoryId 470043. priceIndicator как key","Base layers (/api/geoportal/v1/baselayers): id=235 (ЦОС), id=36347 (ЕЭКО), id=36344 (Ортофото планы 2000) и другие","Cache: в ответе видны cache.levels_to (max zoom), refresh_before для временного инвалидирования","External tiles: есть в базовом списке с 'external' source. Пример 'https://nspd.gov.ru/cgk/map/38/tms/{z}/{x}/{y}.png' (TMS-паттерн)","Для GenDesign: можно встраивать эти тайлы в наши Mapbox/Leaflet как base/overlay. Авторизация через cookie session, но physic-вход работает для layer 235","Остальные полезные endpoints geoportal:","/api/geoportal/v1/page-search-settings?pageCode={code} — настройки поиска. Для marketAnalytics regex='^\\d{2}:\\d{2}:\\d{1,7}:\\d+$' — формат кадастрового номера"]}
{"type":"entity","name":"NSPD_PII_Leak_Apr26","entityType":"research","observations":["Security observation НСПД (26.04.2026): ПД в localStorage браузера.","После ESIA-входа SPA сохраняет в localStorage ключ NSPD_API_CLIENT_USER (~657 char) с данными текущего юзера (вероятно ID, name, email, expires и др.)","Парный ключ NSPD_API_CLIENT_USER_EXPIRES с ISO-датой истечения (обычно +30 мин от входа)","Риск (medium): любой скрипт на странице (в т.ч. 3rd-party вроде Yandex Metrika, или при XSS) может прочитать ПД. Best practice = хранить ПД только в HttpOnly cookie или server-side, не в localStorage","Yandex Metrika с _ym_uid + _ym_d + webvisor (96513913) работает на всех страницах включая профиль — теоретически может видеть PII в страницах","JWT в cookie HttpOnly — это ок, JS не видит. Но всё равно видно в DevTools Network и в cookie storage браузера","JWT response body в ответе /oauth2/token (в сыром plaintext): возвращает распакованные claims в JSON в ответе — display_name, email, family_name, given_name, middle_name, sub UUID, uid UUID, sid — всё это PII","Для GenDesign: прямая интеграция НСПД в наш продукт = ПЛОХО: брал бы слишком большую поверхность PII. Лучше server-side прокси с одним общим сервис аккаунтом (если будет выдан) или использовать CSV-датасеты (DataSource_Rosreestr_DealsCSV_Apr26) и WMTS-плитки без входа (если публичные слои работают без cookie)"]}
{"type":"entity","name":"NSPD_MarketAnalytics_FullArchitecture_Apr26","entityType":"api_spec","observations":["Дата: 26.04.2026 вечер. Полная архитектура /api/market-analytics/v1/* — раскрыта через debug-браузер с физик-аккаунтом ESIA.","АРХИТЕКТУРНЫЙ ПАТТЕРН: серверная сессия фильтров. Фронт сохраняет выбор фильтров на бэке через saveUserFilters → бэк хранит как userFiltersId (число). Все data-endpoints читают активные фильтры из этой сессии — поэтому body=`{}` или совсем без body.","FLOW (порядок вызовов):","1) GET /user-filters/userFilters → текущее состояние фильтров пользователя {userFiltersId, dataSourceSysName, filters[]}","2) Пользователь меняет фильтры в UI → собирающие вызовы /period, /region-list, /settlement, /cadastral-quarter (все POST с подсказками для следующего уровня)","3) Кнопка «Применить» → POST /user-filters/saveUserFilters с полным телом фильтров. Возвращает {userFiltersId: N}","4) После save фронт автоматически дёргает: graphEgrnHistogram, graphEgrnLineIndicator, graphEgrnCandleMedian, graphEgrnLineMedian, tableEgrn, geomDataForHeatMap, dataOnLegend, titleHeatMap","BODY saveUserFilters (правильный формат):","{ dataSourceSysName: 'fgisEgrn', filters: ["," {sysName:'dataSource', options:{value:'ФГИС ЕГРН', id:1}},"," {sysName:'calculationMethod', options:{value:'К предыдущему периоду', id:2}},"," {sysName:'areaRanges', options:{value:'от 25 до 40', id:1}},"," {sysName:'indicators', options:{value:'Индикатор цен квартальный', id:2, periodType:'Q'}},"," {sysName:'periodFrom', options:{value:'4 квартал 2025', sortOrder:32, isRemote:true}},"," {sysName:'periodTo', options:{value:'1 квартал 2026', sortOrder:33, isRemote:true}},"," {sysName:'federalDistrict', options:{valueList:[{code,title}], isSelectAll:true|false}},"," {sysName:'federalSubject', options:{valueList:[{code,title}], isSelectAll:true|false}},"," {sysName:'settlement', options:{valueList:[{code,title}], isSelectAll:false}}","]}","POSTПОДСКАЗКИ при выборе фильтров (важная деталь — все обёрнуты в params!):","POST /period body={params:{type:'M'|'Q'|'H'|'Y', dataSourceSysName:'fgisEgrn'}} → список доступных периодов с sortOrder","POST /region-list body={districtIds:[6]} → список субъектов в выбранных ФО (НЕ /federal-subject!)","POST /settlement body={subjectIds:[1,2,3,4]} → нас.пункты по subject id (массив до 4-5 за раз, фронт батчит)","POST /cadastral-quarter body={subjectIds:[1,2,3,4]} → массив кадастровых кварталов формата '02:55:020113'","DATA ENDPOINTS (body={} или GET, читают по userFiltersId из cookie):","POST /tableEgrn/fgisEgrn?page=0&count=10 → {headers:[{key,name,columnType}], bodyData:[{1:Территория, 2:значение_period1, 3:значение_period2}], meta:{page,count,totalCount}}","POST /fgisEgrn/geomDataForHeatMap → GeoJSON FeatureCollection. Координаты в EPSG:3857 (Web Mercator). 13 цветовых бакетов: <0.25, 0.25-0.5, 0.5-0.7, 0.7-0.85, 0.85-0.95, 0.95-1.0, 1.0_unchanged, 1.0-1.05, 1.05-1.15, 1.15-1.3, 1.3-1.5, 1.5-1.75, >1.75. MultiPolygon границы кадастровых кварталов с цветом по индикатору","GET /graphEgrnHistogram/fgisEgrn → {chartType:'histogramChart', data:[{title, indicatorValueCurrent:0.88, indicatorValuePrevious:1.12, period:'02.2026', percentValue:-21}]}","GET /graphEgrnLineIndicator/fgisEgrn → {chartType:'lineChartIndicator', data:[{title, indicatorValue:1.12, period:'01.2026', periodType:'Месяц'}, ...]}","GET /dataOnLegend/fgisEgrn → описание легенды теплокарты","GET /fgisEgrn/titleHeatMap → {title:'Индикатор цен ежемесячный по выбранной территории...'}"]}
{"type":"entity","name":"NSPD_OrgOnly_Endpoints_Apr26","entityType":"research","observations":["Дата: 26.04.2026. ⚠ КРИТИЧНОЕ ОТКРЫТИЕ — endpoints скрытые от physic-аккаунта (403 Forbidden):","GET /api/market-analytics/v1/graphEgrnCandleMedian/fgisEgrn — СВЕЧНОЙ график медианной АБСОЛЮТНОЙ цены сделок (₽/м²)","GET /api/market-analytics/v1/graphEgrnLineMedian/fgisEgrn — линия медианной АБСОЛЮТНОЙ цены сделок","Все остальные graph endpoints (Histogram, LineIndicator) возвращают только относительные индикаторы (текущий период / предыдущий = 0.88), а Candle/Line Median должны возвращать реальные ₽/м² по кадастровому кварталу.","Для physic (как у юзера сейчас) — 403 'Forbidden'. Проверено эмпирически в браузере 26.04.2026.","ГИПОТЕЗА: доступно для organisation-аккаунта (юрлицо в ESIA) или для аккаунтов с расширенным scope.","ЭКВИВАЛЕНТНОСТЬ ДАННЫХ: эти endpoints дублируют то, что мы уже получаем из CSV-датасета Росреестра (DataSource_Rosreestr_DealsCSV_Apr26) — медианные цены сделок по кадастровым кварталам. Только тут это онлайн-API с фильтрами по периоду/площади/нас.пункту, а CSV — сырые сделки покварталу.","ДЛЯ GenDesign: ничего не теряем. Используем CSV-датасет (per-deal сырые данные) + публичные индикаторы NSPD (относительная динамика) + dom.рф per-flat snapshot. Org-аккаунт NSPD — НЕ требуется."]}
{"type":"entity","name":"NSPD_DataValue_For_GenDesign_Apr26","entityType":"research","observations":["Дата: 26.04.2026. Конкретный value NSPD MarketAnalytics для GenDesign Plan A.","ИСТОРИЯ ДАННЫХ: 33 квартала (Q1 2018 — Q1 2026, 8 лет longitudinal)","ВРЕМЕННЫЕ РАЗРЕЗЫ: M (месяц), Q (квартал), H (полугодие), Y (год). Месячный показатель работает с лагом ~1-2 мес (на 26.04.2026 показывает 02.2026)","МЕТРИКА: индикатор цен — отношение текущего периода к базе/предыдущему/ГОГ. Безразмерное число (0.88 = -12% к предыдущему). Полезно для тренда, не для абсолютных значений","ГРАНУЛЯРНОСТЬ: до уровня кадастрового квартала (формат XX:YY:ZZZZZZ). Это в 100-1000 раз тоньше чем Росстат (агрегат по региону).","КОНКРЕТНЫЙ КЕЙС Свердл.обл, Екатеринбург, площадь 25-40 м², 02.2026 vs 01.2026: индикатор=0.88 (цены упали на 12%), предыдущий период 1.12.","ВЫГОДА для GenDesign:","1) Cross-validation цен сделок с Росреестра CSV — индикатор NSPD должен совпадать с (median_current_quarter / median_previous_quarter) из CSV","2) ВЕЛОСИТИ (sigma trend): тренд цен по конкретному кадастровому кварталу — для финмодели это хороший signal","3) ВЫБОР АНАЛОГОВ: GeoJSON-полигоны кадастровых кварталов с раскраской по индикатору → для участка пользователя автоматически найти кадастровые кварталы вокруг с похожей динамикой","4) WMTS-тайлы (через /api/aeggis/v4/235/wmts/{z}/{x}/{y}.png) можно встроить как base layer в Mapbox/Leaflet GenDesign","ПЛАН ИНТЕГРАЦИИ В Stage 2a:","Шаг A: ESIA-логин в headless Chrome (или через cookie из user-input) → получаем JWT в authAccessToken cookie","Шаг B: для каждого региона интереса (Свердл.обл, МО, Москва) сохраняем фильтры (saveUserFilters) и тянем geomDataForHeatMap → сохраняем GeoJSON в PostGIS как материализованное представление","Шаг C: cron 1×в сутки обновляем индикаторы по периоду и пересчитываем materialized views","Шаг D: для каждого участка пользователя — JOIN с PostGIS по геометрии → находим включающий кад.квартал → читаем индикатор","JURISDICTION: NSPD — государственный сервис Росреестра по 8-ФЗ. Использование физик-аккаунта легально как пользователя. ⚠ автоматизированный сбор через ESIA — серая зона. Лучше ОДНОРАЗОВО собрать с физик-аккаунта и кешировать локально.","ОГРАНИЧЕНИЯ:","1) physic-аккаунт через ESIA — доступ только для одного юзера, RPS-лимиты на сессию","2) JWT TTL=30 мин (refreshable). Для cron нужно либо хранить refresh_token, либо на каждом запуске re-auth через ESIA (что НЕ автоматизируется без обхода капчи)","3) Авторизация через ESIA подвержена captcha/2FA — недетерминирована для headless","4) absolute medians (Candle/Line Median) — 403, требуют org-аккаунт","5) Лимит на массовые запросы кадастровых кварталов: фронт батчит по 4-5 субъектов за раз — видимо есть soft-rate-limit"]}
{"type":"entity","name":"Domclick_DDF_Report_Nov2025","entityType":"research","observations":["Отчёт Домклик «Строительная отрасль на пороге структурной трансформации», представлен на Domclick Digital Forum, ноябрь 2025","Источник: PDF DDF_Потребность в недвижимости.pdf, 29 слайдов","Главный тезис: рынок входит в фазу СТРУКТУРНОЙ ТРАНСФОРМАЦИИ — количественный рост сменяется качественным; покупатели хотят УЛУЧШЕНИЯ характеристик, а не просто отдельной квартиры","Ключевые источники данных в отчёте: SberIndex (цены сделок и объявлений по регионам и 760 городам), Объединённое Кредитное Бюро (повторные ипотечники), Росстат (обеспеченность, население), Ипотечные витрины Сбербанка (миграция покупателей), НАШ.ДОМ.РФ (объёмы стройки)","ВАЖНО для GenDesign: SberIndex даёт цены СДЕЛОК и ОБЪЯВЛЕНИЙ по регионам и 760 городам — источник не использовался в DataSources_Analysis_Apr26, надо изучить (sberindex.ru, SberIndex PRO для городов)","Стратегический вывод: цели должны быть ДИФФЕРЕНЦИРОВАНЫ по регионам и КАЧЕСТВЕННЫ, а не количественны (33 м²/чел к 2030 / 38 м²/чел к 2036 — это нацели Указа 309 от 7 мая 2024)","5 ключевых сигналов для девелоперов: 1) Снижение доступности → переориентация на состоятельных покупателей, 2) 79% гэпа первичка/вторичка = качество, 21% = ставка, 3) Альтернативные сделки усложнились (с +19м² в 2019 до +9м² в 2025), 4) Повторные ипотечники теперь 37% выдач (vs 25% в 2020), 5) Только 19 регионов имеют демографический драйвер для стройки"]}
{"type":"entity","name":"Affordability_Trends_DDF_Nov2025","entityType":"research","observations":["Данные по доступности жилья из отчёта Domclick DDF (ноябрь 2025), для GenDesign Tile2 «По какой цене»","ДИНАМИКА ЦЕН РФ январь 2020 = 0%: первичка +142%, вторичка +104%, ЗП +101% к 2025","СТРУКТУРА ИПОТЕКИ — переориентация на новостройки: 2020-2023 первичка 29% / вторичка 71%; 9м2025 первичка 47% / вторичка 53% (рост ставок выгнал спрос с готового жилья)","ИНДЕКС ДОСТУПНОСТИ (м² для медианного работника при ипотеке 50% от ЗП, 20% взнос, 20 лет): первичка РФ стабильна 32.1 → 31.5 м² (ЗП +15, цены -23, ставки +7), вторичка обвалилась 37.7 → 22.8 м² (ЗП +15, цены -19, ставки -11)","В МОСКВЕ доступность ниже в 2 раза: первичка 23.2 м², вторичка 11.5 м²","ПРОГНОЗ: при снижении ставок будет ОБРАТНЫЙ переток с новостроек на готовое жильё → застройщикам надо готовиться к падению спроса на первичку","СРОК НАКОПЛЕНИЯ ВЗНОСА 20% на 65 м² (50% медианной ЗП на вклад): 2019 → 2025 РФ 2.3 → 6.2 года (×2.7)","ХУДШИЕ для накопления: Алтай 11.8 лет, Москва 7.8, Астраханская 7.7, Татарстан 7.4, Дагестан 7.3, Нижегородская 7.0, Краснодарский 6.9, СПб 6.8, Адыгея 6.7, Омская 6.7","ЛУЧШИЕ для накопления: ЯНАО 2.9, Саха 3.5, ХМАО 3.5, Псковская 3.6, Коми 3.8, Оренбургская 3.8, Архангельская 3.8, Карелия 4.0, Новгородская 4.0, Калужская 4.1","% работающих кто может накопить за 2 года: РФ 8.3%; ЛУЧШИЕ — Оренбургская 19.2%, ХМАО 18.4%, Коми 16.7%, Смоленская 14.1%, Красноярский 13.9%, Архангельская 13.6%, Тюменская 13.5%, Вологодская 13.3%, Калужская 13.0%, Курская 12.6%; ХУДШИЕ — Дагестан 3.5%, Нижегородская 5.0%, Татарстан 5.2%, Омская 5.7%, СПб 6.2%, Кировская 6.3%, Забайкальский 6.5%, Краснодарский 6.6%, Москва/Ленинградская 6.9%","ИНСАЙТ для GenDesign: Свердл.обл НЕ упомянута среди топов и хвостов — значит средние показатели по РФ. Использовать индекс доступности м² как один из факторов финмодели Tile2"]}
{"type":"entity","name":"PriceGap_Quality_vs_Rate_Nov2025","entityType":"research","observations":["Из отчёта Domclick DDF (ноябрь 2025): 79% разрыва цен первичка/вторичка по РФ — следствие КАЧЕСТВА жилья, а не разности ипотечных ставок","ЦЕНЫ 9м2025 (тыс ₽/м²) РФ: первичка 174, новая вторичка моложе 5 лет 161, вся вторичка 115. Гэп -34% общий = -27% качество + -7% ставка","МОСКВА: 357 / 342 / 308. Гэп -14% = -10% качество + -4% ставка","РЕГИОНЫ (без Москвы и СПб): 144 / 134 / 98. Гэп -32% = -25% качество + -8% ставка","КРИТИЧЕСКИЙ ИНСАЙТ: дисконт НОВОЙ вторички (моложе 5 лет) к первичке всего 7% по РФ. То есть НОВОСТРОЙКИ НЕ ТЕРЯЮТ В ЦЕНЕ при перепродаже после ввода — это чистый информационный сигнал для финмодели GenDesign (TestFit и rTIM этого не учитывают)","ДИСКОНТ ВТОРИЧКИ К ПЕРВИЧКЕ ВЫРОС с -20% (2019) до -34% (9м2025) по РФ","САМЫЙ БОЛЬШОЙ ДИСКОНТ (выгодные регионы для альтернативных сделок 'продал вторичку → купил первичку'): Астраханская -52%, Пермский -46%, Дагестан -43%, Хабаровский -43%, Башкортостан -43%, Иркутская -41%, Татарстан -40%, Свердловская -38%, ХМАО -38%, Тульская -38%","САМЫЙ МАЛЕНЬКИЙ ДИСКОНТ (вторичка дорогая): Псковская -9%, Москва -14%, Ставропольский -14%, Краснодарский -14%, Курская -15%, Орловская -16%, СПб -16%, Чувашия -16%, Архангельская -17%, Бурятия -18%","⭐ СВЕРДЛОВСКАЯ ОБЛ ВХОДИТ В ТОП-10 С САМЫМ БОЛЬШИМ ДИСКОНТОМ -38% — для жителя Екб альтернативная сделка ('продал вторичку — купил первичку') математически невыгодна по площади. Это объясняет почему в Екб все идут в первичку через ипотеку, а не через размен"]}
{"type":"entity","name":"AlternativeDeal_Trends_Nov2025","entityType":"research","observations":["Из Domclick DDF (ноябрь 2025): альтернативные сделки (продажа имеющейся вторички 45 м² → покупка первички через ипотеку) теряют эффективность","ДИНАМИКА для РФ при платеже 50% от медианной ЗП: 2019 → 2020 → 2021 → 2022-2024 → 9м2025 = 59 / 64 / 59 / 53 / 54 м²","Прирост площади: 2019 +19 м², 2020 +15 м², 2021 +8 м², 2022-2024 +9 м², 9м2025 +9 м² (теряется в 2 раза за 6 лет)","САМАЯ ВЫСОКАЯ ДОСТУПНОСТЬ (м² можно купить из 45 м² вторички): ЯНАО 93, Камчатка 86, Якутия 86, Архангельская 82, Бурятия 78, Псковская 78, Сахалин 76, Приморский 74, Оренбургская 72, Орловская 72","САМАЯ НИЗКАЯ ДОСТУПНОСТЬ: Астраханская 44, Алтай 47, Татарстан 49, Омская 50, Пермский 51, Башкортостан 52, Нижегородская 52, СВЕРДЛОВСКАЯ 55, Крым 56, Москва 56, СПб 58","⭐ В СВЕРДЛОВСКОЙ ОБЛ продав 45 м² вторички, купить можно 55 м² первички (28 вторичка + 28 ипотека). Прирост всего +10 м² — это ниже среднего РФ (+9 м² с большим разбросом)","ИНСАЙТ для GenDesign: финмодель должна учитывать что в Свердл.обл альтернативные сделки даются с трудом → клиент Prinzip это либо первая ипотека, либо иногородний (по slide 14 — Свердл.обл не упоминается среди магнитов миграции, значит почти всё локальное население)"]}
{"type":"entity","name":"RepeatedMortgage_Nov2025","entityType":"research","observations":["Из Domclick DDF (ноябрь 2025): доля повторных ипотечников выросла с 25% (2020) до 37% (9м2025)","9м2025: 20% берут повторно (нет непогашенных ипотек) + 17% берут 2+ ипотеку (есть непогашенные) = 37% всех повторных","2020: 10% повторно + 15% 2+ = 25%","2024: 18% повторно + 16% 2+ = 34%","ИНТЕРПРЕТАЦИЯ: квартиры всё больше продаются СОСТОЯТЕЛЬНЫМ покупателям, кого надо УБЕДИТЬ повторно улучшить жилищные условия. Source: Объединённое Кредитное Бюро","СЛЕДСТВИЕ для маркетинга Prinzip: customer persona 2025 ≠ first-time buyer; чаще upgrade-покупатель с продажей текущей квартиры. Финансово более готов, но требует большего качества (локация, класс, инфраструктура)","ИНСАЙТ для GenDesign: для финмодели и smart-unit-mix важно — в каждом районе доля повторных ипотечников может различаться. Если в Екб эта доля выше среднего РФ → таргетировать апгрейд-сегмент, более крупные/качественные квартиры. Если ниже → first-time, более доступные форматы"]}
{"type":"entity","name":"QualityShift_NewBuild_2021_2025","entityType":"research","observations":["Из Domclick DDF (ноябрь 2025): структурный сдвиг качественных метрик строящегося жилья 2021 → 2025","СРЕДНЯЯ ПЛОЩАДЬ КВАРТИРЫ ПАДАЕТ: РФ 50.1 → 48.3 м² (-1.8); Москва 56.0 → 53.4 м² (-2.6) — застройщики дробят квартиры из-за снижения доступности","ДОЛЯ БИЗНЕС+ЭЛИТНОГО КЛАССА РАСТЁТ: РФ 15% → 17% (+2пп); Москва 45% → 51% (+6пп) — переориентация на богатых","ПАРКОВОЧНЫЕ МЕСТА НА КВАРТИРУ РФ 0.18 → 0.25 (+0.07); Москва 0.40 → 0.35 (-0.06) — в РФ улучшают, в Москве ухудшают (земля дорогая)","ДОЛЯ НЕЖИЛОЙ ПЛОЩАДИ: РФ 16% → 19% (+3пп); Москва 27% → 25% (-2пп) — больше коммерции в регионах, в Москве и так высокая база","ДОЛЯ ПАНЕЛЬНЫХ СТЕН: РФ 4.8% → 5.4% (+0.6пп); Москва 4.3% → 1.2% (-3.1пп) — в РФ возвращается панель из-за себестоимости, в Москве — монолит/кирпич","СРЕДНЯЯ ЭТАЖНОСТЬ: РФ 18.7 → 19.2 (+0.5); Москва 25.0 → 30.9 (+5.9) — рост этажности, особенно в Москве","⭐ КЛЮЧЕВОЙ ВЫВОД: 'Из-за переориентации на богатых клиентов застройщики улучшают качественные характеристики, но СНИЖАЮТ ПЛОЩАДИ новых квартир'","ИНСАЙТ для Plan A Tile1 «Что строить» в GenDesign: при генерации концепции на участке default-параметры должны учитывать тренд — средние площади падают (-1.8 м² РФ за 4 года), доля бизнес+ растёт. Без поправки сгенерируем план образца 2021 года, который не продастся в 2025+"]}
{"type":"entity","name":"RegionGroups_BuildingDemand_Nov2025","entityType":"research","observations":["Из Domclick DDF (ноябрь 2025): 6 групп регионов по потребности в стройке МКД","ГРУППА 1 (9 регионов): ВЫСОКАЯ ПОТРЕБНОСТЬ в строительстве — Москва, Тюменская, ХМАО, ЯНАО, Крым, Калининградская и др. Драйверы: прирост населения вкл. трудовую миграцию, курортная недвижимость, невысокая обеспеченность м²/чел","ГРУППА 2 (11 регионов): УМЕРЕННАЯ ПОТРЕБНОСТЬ — СПб, ЛО, МО, Краснодарский и др. Нет оттока, популярность у иногородних, средняя обеспеченность","ГРУППА 3 (25 регионов): ТОЧЕЧНОЕ СТРОИТЕЛЬСТВО + РЕНОВАЦИЯ — Нижегородская, Приморский, Камчатский и др. Отток или стабильное население, низкая/средняя обеспеченность","ГРУППА 4 (26 регионов, САМАЯ БОЛЬШАЯ): ФОКУС НА РЕНОВАЦИИ — Владимирская, Кировская, Тульская, Псковская и др. Снижение населения, формально высокая обеспеченность, но СТАРЫЙ ЖИЛИЩНЫЙ ФОНД","ГРУППА 5 (3 региона): РЕНОВАЦИЯ + АРЕНДНОЕ ЖИЛЬЁ — Амурская, Архангельская, Иркутская. Снижение населения, старый фонд, крупные предприятия нуждаются в жилье для работников","ГРУППА 6 (11 регионов): ФОКУС НА ИЖС — Северный Кавказ (Дагестан, Чечня, Ингушетия, Каб.-Балкария, Кар.-Черкессия, Адыгея), Республика Алтай, Тыва, Бурятия, Калмыкия, Крым (частично). Высокая доля сельского населения, ИЖС > МКД","ГДЕ СВЕРДЛОВСКАЯ ОБЛАСТЬ: в отчёте явно НЕ названа в группе 1-2, но имеет высокую площадь стр-ва (1.4 м²/чел) при падающем населении (-3.8 до 0%) — попадает в группу 3 ТОЧЕЧНОЕ СТРОИТЕЛЬСТВО + РЕНОВАЦИЯ","СТРАТЕГИЧЕСКИЙ ВЫВОД: только 20 регионов (группы 1+2) нуждаются в БЫСТРОМ увеличении жилого фонда. Остальные 65 — реновация, ИЖС или арендное жильё. Federal-уровень должен дифференцировать поддержку, а не выдавать одинаковую льготную ипотеку всем"]}
{"type":"entity","name":"DemandIndex_Domclick_Nov2025","entityType":"research","observations":["Из Domclick DDF (ноябрь 2025): 'Индекс востребованности строительства жилья (МКД) в регионе' — композитный рейтинг 81 региона","ФАКТОРЫ ИНДЕКСА: 1) обеспеченность м²/чел на 01.01.2025; 2) доля нового жилья (введено 2019-2024); 3) динамика численности населения региона за 5 лет; 4) динамика населения регионального центра за 5 лет; 5) размер регионального центра; 6) доля сельского населения; 7) доля покупателей квартир из 'чужих' регионов; 8) доля населения способного накопить взнос 20% за 2 года; 9) доля населения которому доступна альтернативная сделка (продажа 45 м² → покупка первички); 10) отношение распроданности к стройготовности на 01.10.2025","ТОП-10 (высокая+умеренная востребованность, 31 регион всего): #1 Севастополь, #2 ХМАО, #3 Ставропольский, #4 Хабаровский, #5 Красноярский, #6 Бурятия, #7 Москва, #8 ЯНАО, #9 Тюменская, #10 Камчатка","ХВОСТ-10: #81 Астраханская, #80 Белгородская, #79 Кар.-Черкессия, #78 Липецкая, #77 Пензенская, #76 Тамбовская, #75 Сахалинская, #74 Рязанская, #73 Сев.Осетия, #72 Томская","СВЕРДЛОВСКАЯ ОБЛ — место в индексе НЕ ПУБЛИКУЕТСЯ в отчёте (показаны только топ-10 и хвост-10), но регион не в топ-10 и не в хвосте → средняя или ниже-средней востребованность","ИНСАЙТ для GenDesign: Site Finder может реплицировать аналогичный composite-score (10 факторов выше) на уровне муниципалитетов / кадастровых кварталов внутри Свердл.обл — это уникальный data-product, ЕРЗ и rTIM такого не делают","10 ФАКТОРОВ — почти все вычисляются из наших уже найденных источников: Росреестр CSV (сделки, доступность), ДОМ.РФ (обеспеченность через flatCount, доля нового жилья, распроданность через ready-construction), Росстат (демография, сельское население), Ипотечные витрины Сбербанка (миграция покупателей — нет у нас доступа, но можно прокси через ДомКлик)"]}
{"type":"entity","name":"Regional_Migration_Buyers_Nov2025","entityType":"research","observations":["Из Domclick DDF (ноябрь 2025): доля покупателей квартир в новостройках из ДРУГИХ регионов за 9м2025","Источник: Ипотечные витрины Сбербанка","РФ среднее: 19% покупателей не из своего региона","МАГНИТЫ МИГРАЦИИ (>20%): Крым 56%, Калининградская 37%, Краснодарский 36%, Москва 31%, СПб 26%, Ленинградская 25%, Новосибирская 24%, Тюменская 23%, Ставропольский 22%, Московская 19%","ЗАМКНУТЫЕ РЫНКИ (<10%): Алтайский 6%, Кемеровская 7%, Пермский 7%, Удмуртия 8%, Башкортостан 9%, Пензенская 10%, Челябинская 11%, Иркутская 11%, Омская 11%, Оренбургская 11%","СВЕРДЛОВСКАЯ ОБЛ — НЕ в топ-10 магнитов и НЕ в топ-10 замкнутых. Скорее всего среднее по РФ ~10-15% иногородних покупателей. Драйвер магнитизма — миграция ХМАО/ЯНАО → Екб (северяне выходящие на пенсию)","ИНСАЙТ для Prinzip: в маркетинге учесть что 10-15% покупателей могут быть из ХМАО/ЯНАО/Курганской — таргет-кампании в этих регионах через ВК/Telegram могут быть эффективны","ИНСАЙТ для Site Finder: миграционная доля = +1 фактор скоринга для участков. Города-магниты держат премию к цене, замкнутые рынки — дисконт"]}
{"type":"entity","name":"Sverdlovsk_Profile_DDF_Nov2025","entityType":"research","observations":["Сводка по Свердловской области из отчёта Domclick DDF (ноябрь 2025) — для GenDesign Discovery","ДИНАМИКА НАСЕЛЕНИЯ 2025 vs 2020: -1% до -3.8% (в группе слабого падения, не в худших и не в растущих)","ДОЛЯ СЕЛЬСКОГО НАСЕЛЕНИЯ: 14% (один из самых низких в РФ — урбанизированный регион, среднее РФ 25%)","ОБЕСПЕЧЕННОСТЬ м²/чел: НЕ В ТОП-10 ни хвоста ни головы — средние ~25-32 м²/чел","ПЛОЩАДЬ СТРОЯЩИХСЯ МКД НА 1 ЖИТЕЛЯ: 1.4 м²/чел — ВЫСОКАЯ (top-10 РФ, среднее РФ 0.8 м²/чел)","ИЗМЕНЕНИЕ ОБЪЁМА СТРОЙКИ vs 2019: НЕ в топ-10 роста и НЕ в топ-10 падения, среднее РФ +11.3% — стабильно строит","ДИСКОНТ ВТОРИЧКИ К ПЕРВИЧКЕ: -38% (8-е место в РФ среди регионов с самым большим дисконтом, РФ среднее -34%)","АЛЬТЕРНАТИВНАЯ СДЕЛКА: продав 45 м² вторички, можно купить 55 м² первички (28 вторичка + 28 ипотека). Прирост +10 м² — НИЖЕ среднего РФ (+9 м² с разбросом)","ЕКАТЕРИНБУРГ как региональный центр: входит в группу 'снижение населения области + рост рег.центра' (slide 25, явно подписан на графике) — типичный паттерн для крупного регионального центра","ЕКАТЕРИНБУРГ + ПРИГОРОДЫ: рост и центра и пригородов (slide 26)","МИГРАЦИЯ ПОКУПАТЕЛЕЙ: НЕ в топ-10 магнитов и не в топ-10 замкнутых рынков, среднее РФ ~15-20% иногородних","ИНДЕКС ВОСТРЕБОВАННОСТИ СТРОЙКИ: НЕ в топ-10 и не в хвосте","ИТОГО ПРОФИЛЬ: Свердл.обл = ТИПИЧНЫЙ КРУПНЫЙ ИНДУСТРИАЛЬНЫЙ РЕГИОН с высокой стройкой при умеренно падающем населении, но Екб ABSORBS внутрирегиональную миграцию + северян ХМАО/ЯНАО → концентрация спроса в самом Екб и пригородах","СТРАТЕГИЧЕСКОЕ ОТНЕСЕНИЕ К 6 ГРУППАМ: вероятно Group 3 (точечное стр-во + реновация) или граница Group 1-3","СЛЕДСТВИЕ для Prinzip: фокус на КАЧЕСТВЕ (не количестве), таргет апгрейд-аудитории Екб + сегмент 'покупатели с северов'"]}
{"type":"entity","name":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","entityType":"event","observations":["Дата: 26.04.2026 вечер. ВЕХА: dataset_СДЕЛКИ Росреестра залит на ПРОД в PostgreSQL+PostGIS впервые.","СКАЧАНО: 7 кварталов (2024 Q3 — 2026 Q1) из https://rosreestr.gov.ru/data-sets/. Размер ZIP ≈146 MB, распакованных CSV ≈1.0 GB.","УТОЧНЕНИЕ ГРАФА: в DataSource_Rosreestr_DealsCSV_Apr26 было указано '9 кварталов 2024-2026' — НЕВЕРНО. На самом деле Росреестр НЕ опубликовал dataset_СДЕЛКИ за Q1 и Q2 2024 (в их папках только КАДАСТРСТОИМОСТЬ). Первый доступный квартал: 2024 Q3.","ОСОБЕННОСТЬ URL: имена файлов/папок на сервере в кодировке Windows-1251 (НЕ UTF-8). Корректные URL: https://rosreestr.gov.ru/data-sets/{Q}%20%EA%E2%E0%F0%F2%E0%EB%20{YYYY}%E3./dataset_%D1%C4%C5%CB%CA%C8_r-r_01-92_y_{YYYY}_q_{Q}.csv.zip. Для листинга обязательно Referer: https://rosreestr.gov.ru/data-sets/ (иначе 403)","СРАВНЕНИЕ сепараторов: 2024 Q3 = ';' и имя файла dataset_СДЕЛКИ_r_all_q_3.csv (без разбивки по регионам в имени). 2024 Q4+ = '~' и имя dataset_СДЕЛКИ_r-r_01-92_y_YYYY_q_N.csv. Различие ПРИНЦИПИАЛЬНО для ETL — парсер должен знать оба.","ИТОГОВЫЕ ЦИФРЫ НА ПРОДЕ: 4 975 398 строк-агрегатов, 7 581 266 фактических сделок (с учётом deal_count), 296 040 сделок Свердловской обл. Размер БД: 1.8 GB (deals 1.1 GB + MV 305 MB + индексы)","РАСПРЕДЕЛЕНИЕ ПО КВАРТАЛАМ (сделки РФ / Свердл.обл): 2024Q3 1.108M/40K, 2024Q4 1.265M/48K, 2025Q1 877K/35K, 2025Q2 991K/38K, 2025Q3 1.111M/45K, 2025Q4 1.329M/52K, 2026Q1 898K/37K","СХЕМА PG: rosreestr_deals — partitioned BY RANGE(period_start_date) на 7 квартальных партиций (rosreestr_deals_2024q3 … rosreestr_deals_2026q1). Индексы: (region_code, quarter_cad_number), BRIN(period_start_date), (doc_type) WHERE in ('ДКП','ДДУ'), (realestate_type_code). PRIMARY KEY (id, period_start_date) — из-за партиционирования.","ОБОЙДЕННЫЕ DATA QUALITY ПРОБЛЕМЫ (важны для cron-синка): 1) deal_price бывает битым с десятками цифр → сделали NUMERIC без precision, фильтр на INSERT 'BETWEEN 100000 AND 1e10'. 2) year_build бывает датой '09.07.1988' → регекс ~ '^[12][0-9]{3}$', иначе NULL. 3) wall_material_code бывает multi-value '\\\"code1;code2\\\"' → TEXT вместо VARCHAR(15). 4) area бывает абсурдным (>1e8) → NUMERIC без precision, фильтр 'BETWEEN 5 AND 1000' в MV. 5) region_code бывает NULL → WHERE region_code IS NOT NULL. 6) в Q1 2026 потеряли ~5 строк (похоже на csv-quoting issues, <0.001%)","MATERIALIZED VIEWS созданы 3 шт:"," • rr_agg_cad_quarter (216 MB) — (region, cad_quarter, period, doc_type, area_bucket) → deals_count, p10/median/p90 price_per_sqm, mean. Ареа-бакеты: lt25, 25-40, 40-60, 60-90, 90-150, gt150 (как в NSPD)"," • rr_agg_region (680 KB) — (region, period, doc_type, realestate_type) → deals_count, percentiles. Для Ural-dashboard в prinzipevent.ru/analytics"," • rr_agg_settlement (88 MB) — (region, settlement, period, doc_type, realestate_type) → percentiles + distinct_cad_quarters. Для ГОРОД-tab Екб","REFRESH время: полный build всех 3 MV ~40 сек на проде (2 vCPU). Для Discovery этого хватит — REFRESH вручную или раз в квартал после заливки нового CSV","ВАЛИДАЦИЯ НА ПРОДЕ (smoke-test):"," Екатеринбург КВАРТИРЫ Q1 2026: ДДУ 1 153 сделки median 160 645 ₽/м² (p10=113K, p90=232K, 77 кад.кварталов); ДКП 7 700 сделок median 121 961 ₽/м² (p10=69K, p90=185K, 703 кад.квартала). Гэп ДКП→ДДУ = -24% (близко к Domclick DDF 'РФ -34%')"," Свердл.обл ДДУ динамика по кварталам (median ₽/м²): 2024Q3=38K → 2024Q4=43K → 2025Q1=54K(2 сделки!) → 2025Q2=141K → 2025Q3=140K → 2025Q4=149K → 2026Q1=149K. ДО середины 2025 ДДУ-данные НЕ ПОЛНЫЕ (Q1 2025 = всего 2 сделки в области — явный lag публикации). ДКП вроде ровный рост 63K→63K→66K→66K→70K→75K→79K ₽/м² — выглядит и реалистично","ДОСТУП НА ПРОДЕ: localhost:15432 через SSH-туннель до gendesign@46.173.16.127 (порт 5432 в контейнере docker-compose.prod.yml проброшен на 127.0.0.1:5432 на VPS). Данные живут в docker volume gendesign_postgres_data — переживут redeploy","АРТЕФАКТЫ В РЕПО: data/sql/01_schema_rosreestr_deals.sql, 02_load_all_quarters.sh (поддерживает PG_HOST + PGPASSWORD ENV для remote/tunnel), 03_materialized_views.sql. data/raw/ — 7 распакованных CSV (в .gitignore должны быть)","СЛЕДУЮЩИЕ ШАГИ: 1) добавить data/raw/ в .gitignore (нельзя коммитить 1 GB CSV); 2) сконвертировать 01_schema в Alembic-миграцию (не срочно); 3) cron quarterly_rosreestr_sync на VPS — проверяет listing 16-го числа второго месяца после квартала; 4) ИНТЕГРАЦИЯ с NSPD GeoJSON для spatial join 'участок узера → кадастровый квартал → агрегат из rr_agg_cad_quarter'; 5) FastAPI router /api/v1/analytics/{ural|ekb|prinzip}","ОГРАНИЧЕНИЕ ДЛЯ Prinzip вкладки: связь 'сделки Росреестра → застройщик' НЕ ПРЯМАЯ. Нужен JOIN через quarter_cad_number → NSPD/ПКК polygon → ДОМ.РФ /сервисы/api/kn/flats?developers=6208_0&regions=66 для Prinzip-жк в этом кад.квартале. Эта связь — next sprint."]}
{"type":"entity","name":"DomRF_Analytics_Loaded_Prod_Apr26","entityType":"event","observations":["Дата: 26.04.2026 вечер. ВЕХА: ДОМ.РФ portal-analytics dashboard залит на ПРОД в PostgreSQL.","ИСТОЧНИК: https://xn--80az8a.xn--d1aqf.xn--p1ai/portal-analytics/api/* (наш.дом.рф). 6 endpoints, snapshot от 26.04.2026.","СКАЧАНО:","• /dictionaries/regions — 89 регионов в 9 ФО","• /dictionaries/developers — 2 734 застройщика (в т.ч. PRINZIP id=6208_0)","• /dashboard/by-region — 89 регионов с разбивкой по комнатности (ONE/TWO/THREE/FOUR)","• /dashboard/by-flat-area — 8 area-buckets × 4 комнатности = 40 рядов (FROM_0_TO_25 … FROM_100)","• /dashboard/by-developer — 2 734 застройщика с разбивкой по комнатности (~11K рядов)","• /dashboard/by-room-count — РФ totals (sanity check, не храним)","✅ ПОКРЫТИЕ: 2.4M квартир в строительстве МКД / 118.7M м² по всей РФ. Свердл.обл: 115 205 квартир / 5.67M м² (52% однушки, 35% двушки, 12% трёшки, 1% 4+).","⚠ ОГРАНИЧЕНИЕ: на страницах 'долевое_строительство' и 'показатели_жилищного_строительства' фильтр ?regionId=X ИГНОРИРУЕТСЯ — сервер всегда отдаёт РФ-агрегат. Разбивка по регионам идёт ЧЕРЕЗ by-region (не by-room-count). Для Prinzip-специфичных срезов по Свердл.обл нужны другие endpoints (не проверяли) или /сервисы/api/kn/flats?regions=66&developers=6208_0 с Basic-auth.","ОБХОД WAF: ServicePipe блокирует прямой curl (JS-challenge). Решение: использовали chrome-devtools MCP get_network_request с responseFilePath — берёт response ПРЯМО ИЗ БРАУЗЕРНОГО КАША, обходя WAF/cookies/mixed-content. Для обновления snapshot'а нужен открытый браузер и chrome-devtools MCP. Для production cron — Playwright/Selenium в headless режиме (пройдёт ServicePipe через JS-VM).","СХЕМА PG (5 таблиц):","• domrf_regions(region_id, region_name, federal_district) — 89","• domrf_developers(developer_id TEXT, developer_name) — 2 734. PK = developer_id (формат '6208_0' или '0_14583')","• domrf_snapshots(snapshot_date PK, fetched_at, notes)","• domrf_region_aggregates(region_id, snapshot_date, room_count_type, flat_count, area_sqm, percent) — 89×5=445 (храним TOTAL+ONE/TWO/THREE/FOUR), 439 по факту (у некоторых регионов нет FOUR)","• domrf_flat_area_distribution(snapshot_date, region_id, area_bucket, room_count_type, flat_count, area_sqm, percent) — 40 рядов (region_id=0 = РФ)","• domrf_developer_aggregates(developer_id, snapshot_date, region_id, room_count_type, flat_count, area_sqm, percent) — 11 063 рядов (region_id=0 = РФ)","КЛЮЧЕВЫЕ ЦИФРЫ PRINZIP (id=6208_0): 814 квартир / 31 040 м². Квартирография: 614 однушек (75%, 18 922 м²), 156 двушки (19%), 22 трешки (3%), 22 4+комн. (3%). Сравнение со Свердл.обл в целом (52/35/12/1) — PRINZIP сильно смещён в однушки (75% vs 52% benchmark).","ТОП-10 РФ застройщиков (по flat_count): Самолет 110 568 / ПИК 84 007 / DOGMA 66 308 / ТОЧНО 46 870 / Setl Group 44 817 / ФСК 39 888 / ССК 35 547 / ЮгСтройИнвест 35 471 / ЛСР 33 933 / Брусника 30 106","СВЕРДЛ.ОБЛ КОНКУРЕНТЫ PRINZIP в реестре: Атомстройкомплекс (5772_0), ЛСР (5653_0), КОРТРОС (5654_0), Стройтэк (4647_0), УГМК-ЗАСТРОЙЩИК (5786_0), Брусника (5791_0), СЗ ЛСР.ОСТРОВ (0_23239), Стройтэкс (5973_0). Отношение PRINZIP к Свердл.обл не хранится напрямую в ДОМ.РФ dashboard агрегатах (их by-region API не возвращает dev-детали), но видно что в Свердл.обл 115K квартир, PRINZIP 814 = ~0.7% рынка (маленький игрок)","СТРУКТУРА ПЛОЩАДЕЙ РФ (benchmark): 0-25м² 6%, 25-35м² 17%, 35-45м² 30% (мода!), 45-55м² 14%, 55-70м² 20%, 70-85м² 8%, 85-100м² 3%, >100м² 2%. Медиана ~45 м².","АРТЕФАКТЫ В РЕПО: data/sql/10_schema_domrf.sql, data/sql/11_load_domrf.py (Python loader через docker run psql), data/sql/upload_server.py (был использован но заблокирован Mixed-Content). data/raw/domrf/*.json — 6 файлов сырых (в .gitignore)","СЛЕДУЮЩИЕ ШАГИ: 1) искать endpoints с regionфильтром для разбивки по застройщикам в конкретном регионе (возможно другая страница или /flats/map?regions=66&developers=6208_0 с Basic MTpqd2U=); 2) /сервисы/api/kn/flats?regions=66 — поквартирный прайс-лист Свердл.обл (~24K квартир); 3) ДОМ.РФ ready-construction (sold%/ready%) — velocity для Tile3 Plan A; 4) ЦБ ипотека (Tab11) — желательно иметь отдельной таблицей; 5) MV «top_developers_in_region» после появления регионного среза"]}
{"type":"entity","name":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","entityType":"event","observations":["Дата: 26.04.2026 вечер (продолжение). ВЕХА: 7 файлов ДОМ.РФ (XLSX+PDF), скачанных юзером вручную через кнопку 'Скачать' на наш.дом.рф, залиты на ПРОД. Расширяет JSON-dashboard данные из DomRF_Analytics_Loaded_Prod_Apr26.","ИСТОЧНИКИ (C:\\Users\\user\\Downloads\\):","• developer_rf_26-04-2026.xlsx — 2746 застройщиков (2563 уникальных после дедупа), поля Площадь/Разрешения/Дома/Квартиры/доля%","• escrow_rf_26-04-2026.xlsx — 28 банков, эскроу-показатели (дома/разрешения/площадь/застройщики/регионы)","• guaranty_26-04-2026.xlsx — 99 территорий (РФ + 8 ФО + 89 регионов) с разбивкой всего/214-ФЗ/эскроу/ПП480","• housing_info_26-04-2026.pdf — РФ-разбивка по механизмам (все/эскроу/фонд/без) + топ-10 регионов + топ-10 городов + план ввода 2026-2035","• sold_out_info_26-04-2026.pdf — реализация МАРТ 2026 (отчёт от 11.04.2026), РФ итог + 8 регионов + разбивка по году ввода + распределение по % реализации","• Квартирография_жилищного_строительства_26-04-2026.pdf — топ-20 застройщиков + топ-20 регионов (дублирует JSON dashboard данные, не загружали отдельно)","• mortgage_rates_19-04-2026.pdf — ставки топ-20 банков на 19.04.2026","СХЕМА PG (9 таблиц + 4 индекса):","• domrf_developers_full(snap, name, area_th_sqm, permits, houses, flats, market_share_pct) — 2 563 ряда","• domrf_escrow_banks(snap, bank_name, houses, permits, area_th_sqm, devs, regions) — 28 рядов","• domrf_guaranty_regions(snap, territory, level, total_*, fz214_*, escrow_*, pp480_*) — 99 рядов, level∈{rf,fo,region}","• domrf_housing_summary(snap, territory, level, mechanism, devs, permits, decls, houses, area, flats) — 58 рядов, mechanism∈{all,escrow,fund,no_attraction}","• domrf_planned_commissioning(snap, plan_year, escrow_th, fund_th, no_attr_th, total_th) — 10 лет (2026-2035)","• domrf_sold_out(snap, territory, total/sold/unsold/not_open _area+%, avg_price_per_sqm, attracted_funds_mln) — 9 рядов","• domrf_sold_out_by_year(snap, plan_year, total, pct, sold/unsold/not_open %) — 6 рядов (2026..2031+)","• domrf_sold_out_by_progress(snap, progress_bucket, total, pct, sold/unsold within %) — 6 корзин (not_open..80+)","• domrf_mortgage_rates(snap, bank, primary_rate, secondary_rate, refinance_rate, note) — 20 банков","КЛЮЧЕВЫЕ ЦИФРЫ ПОСЛЕ ЗАГРУЗКИ:","• PRINZIP в полном реестре: 31.04 тыс м² / 2 дома / 814 квартир / доля рынка РФ 0.026% (совпадает с JSON dashboard)","• Свердл.обл guaranty: 5654 тысм² / 179 застройщиков (178 на эскроу) — НОВОЕ: теперь есть число застройщиков по каждому региону (раньше были только объёмы)","• Свердл.обл sold_out: 5686 тысм² / продано 29% / не продано 54% — НИЗКИЙ sold_rate (Москва 47%, СПб 40%) → структурная проблема рынка в РФ (по среднему 31% продано), в Свердл.обл хуже среднего","• РФ sold_out: 119M м² / 31% продано / 45% не продано / 24% продажи не открыты. Средняя цена МКД РФ: 216 316 ₽/м². Объём привлечённых средств: 7.95 трлн ₽","• ПРОГНОЗ ВВОДА: 2026 = 37.9M м² → 2027 = 35.4M → 2028 = 26.5M → 2029 = 11.0M → 2030 = 4.3M (РЕЗКОЕ ПАДЕНИЕ ПОСЛЕ 2028)","• ТОП-5 БАНКОВ ЭСКРОУ: Сбер 72.8M м² (61% рынка!), ВТБ 17.4M, ДОМ.РФ 13.3M, Альфа 5.7M, ГПБ 2.6M. СБЕР ДОМИНИРУЕТ эскроу-рынком","• СТАВКИ ИПОТЕКИ 19.04.2026: средневзвешенная 19.90% первичка / 19.59% вторичка / 18.81% рефинанс. Самые низкие: Кубань Кредит 16.4%, Т-Банк 16.9%, Уралсиб 17.89%, Металлинвест 18.1%. Самые высокие: Сбер 20.2%, Совком 19.99%, ВТБ 19.9%","НОВЫЕ СРЕЗЫ КОТОРЫХ НЕ БЫЛО:","1) ЧИСЛО ЗАСТРОЙЩИКОВ ПО КАЖДОМУ РЕГИОНУ (из guaranty.xlsx) — раньше этого не было в JSON dashboard. Свердл.обл 179, Москва ~1057 (ЦФО), Краснодарский …","2) РАСПРЕДЕЛЕНИЕ ПО МЕХАНИЗМАМ (эскроу/фонд/без) — в РФ 96% площади на эскроу, 1% фонд, <1% без. Активных застройщиков 4 336 всего","3) РЕАЛИЗАЦИЯ sold/unsold (Tile3 velocity) — был отложен в роадмапе как 'TODO ready-construction', теперь есть на уровне регионов/года-ввода/бакета-реализации","4) СРЕДНИЕ ЦЕНЫ ПЕРВИЧКИ РФ (216 316 ₽/м² на март 2026) — бенчмарк для Tile2 (раньше были только Росреестр ddu_median по кад.кварталам)","5) СТАВКИ ПО БАНКАМ — отдельный срез который не был в dashboard JSON, полезен для финмодели","6) ПЛАН ВВОДА ДО 2035 ГОДА — видно резкое падение после 2028 года (соответствует Domclick DDF '27 регионов строят меньше')","ОГРАНИЧЕНИЕ: все данные — РФ итоги или топ-N. НЕТ связи 'застройщик × регион' в PDF/XLSX — для Prinzip-специфичных срезов по Свердл.обл нужен /сервисы/api/kn/flats?regions=66&developers=6208_0 с Basic-auth (не выкачано ещё)","ОБХОД WAF: в этот раз юзер сам скачал файлы через кнопку в браузере (XLSX/PDF экспорт на портале), это обошло WAF без chrome-devtools MCP. Для cron — нужен Playwright (эмулировать клик + download)","АРТЕФАКТЫ: data/sql/20_schema_domrf_extras.sql, data/sql/21_load_domrf_extras.py. Исходные файлы остаются в C:\\Users\\user\\Downloads\\ (не копируем в репо — user-private)"]}
{"type":"entity","name":"DomRF_Playwright_Scraper_Apr26","entityType":"infrastructure","observations":["Дата: 26.04.2026 вечер. Продакшн-скрейпер ДОМ.РФ на Playwright + headless Chromium","АРТЕФАКТ: data/sql/30_scrape_domrf.py — проходит ServicePipe WAF, собирает все /api/* JSON ответы с 12 страниц наш.дом.рф. Поддерживает --headed для отладки, --page <name> для одной секции","РАБОТАЕТ БЕЗ ОТКРЫТОГО БРАУЗЕРА: Playwright сам запускает Chromium в headless режиме, проходит JS-challenge ServicePipe","ПОКРЫТИЕ: из 12 страниц успешно скачал 7 (launch / share_construction / escrow / sold_ready / quartirografia / commissioning / mortgage_stats)","НЕ СКАЧАЛОСЬ (5 страниц пустых): housing, housing_dev, realization, mortgage_rates, stat_series. Причина: эти страницы делают API-вызовы только при user-interaction (клики на фильтры/вкладки) или их инициируют из сервис-воркера. Требуется расширить скрейпер page-specific взаимодействиями (клик на вкладки, выбор фильтров)","СКАЧАНА СТАТИСТИКА: 64 JSON-файла, ~1.95 MB сырых данных в data/raw/domrf_full/<section>/","РАСШИРЕНИЕ size=15 → size=1000: скрейпер автоматически делает второй fetch с size=1000 для всех endpoint'ов где был size=15 — получаем все регионы/застройщики вместо топ-15","ИСПОЛЬЗОВАНИЕ ДЛЯ cron: pip install playwright + python -m playwright install chromium. Готов использоваться на VPS Beget — нужен ~300 MB для Chromium"]}
{"type":"entity","name":"DomRF_Scraped_Loaded_Prod_Apr26","entityType":"event","observations":["Дата: 26.04.2026 вечер. Нормализованные данные из Playwright-скрейпера загружены в 10 НОВЫХ PG-таблиц на ПРОДЕ","СХЕМА: data/sql/31_schema_domrf_full.sql + 32_load_domrf_full.py","НОВЫЕ ТАБЛИЦЫ (10 шт, не пересекаются с существующими):","• domrf_launch_top (1 410 рядов) — топ-N застройщиков/регионов/городов/ФО по запускам (app) и вводу (rnv). dim_type × metric_type × entity_id","• domrf_launch_obj_class (4) — разбивка запусков/ввода по классу (Типовой/Комфорт/Бизнес/Элитный)","• domrf_launch_monthly (75) — временной ряд год+месяц → app/rnv (2020-2026)","• domrf_sold_ready_index (1) — РФ итог на март 2026: 118.88M м² всего, продано 30.91%, готовность 43.1%, soldReady 71.73%","• domrf_sold_ready_breakdown (2 660 рядов) — распроданность по ФО/регионам/городам/застройщикам с squareSum/soldPerc/readyPerc/soldReadyPerc","• domrf_sold_ready_dynamics (300) — динамика 4 индикаторов (squareSum/sold%/ready%/soldReady%) по годам и месяцам с 2020 по 2026","• domrf_project_finance (99) — долевое стр-во по федэкроу/214-ФЗ/ПП480 для РФ+ФО+регионов (rns_cnt, dev_cnt, liv_sq_amt + guaranty_escrow_*)","• domrf_commissioning (1) — фактический ввод по регионам (multifamily/private)","• domrf_mortgage_dashboard (1) — ОБЩАЯ СТАТИСТИКА ИПОТЕКИ РФ: 68 714 кредитов (22 595 первичка + 46 119 вторичка), средние ставки: ПЕРВИЧКА 6.83% (субсидированная!), ВТОРИЧКА 12.95%","• domrf_mortgage_details (2) — разбивка по валюте RUB/OTH (средний кредит 4.22 млн ₽, 23.8 лет срок, просрочка 1.02%)","КЛЮЧЕВЫЕ ИНСАЙТЫ:","1) ТОП-5 РФ ПО ЗАПУСКАМ 2026: DOGMA 492K м², Setl Group 427K, Самолет 360K, ФСК 257K, ССК 257K. ПИК (лидер строительства) 6-е место по НОВЫМ запускам — значит доводят имеющееся, не расширяются","2) СВЕРДЛОВСКАЯ ОБЛ ЗАПУСКИ 2026: 492 478 м² (6-е место в РФ после МО/ЛО/Москвы/Краснодар/Башкортостан)","3) СВЕРДЛОВСКАЯ РАСПРОДАННОСТЬ (март 2026): 5 686 тыс м² / продано 29.04% / готовность 36.08% / soldReady 80.47%. soldReady > 80% = хороший баланс между продажами и стройкой (не затоварены)","4) РЕЙТИНГ ФО ПО soldReady%: ЦФО 84.4%, СЗФО 80.6%, ПФО 71.8%, ДФО 71.6%, СибФО 63.0%, СКФО 36.0% (плохо!), УрФО 66.4%, ЮФО 59.4%. СКФО строит быстро (ready 47.9%) но продаёт медленно (sold 17.2%)","5) КЛАСС ЖИЛЬЯ ПО ЗАПУСКАМ (м²): Типовой 1.965M, Комфорт 6.929M (ЛИДЕР!), Бизнес 1.340M, Элитный 326K. Комфорт = 67% всех запусков","6) СВЕРДЛ.ОБЛ PROJECT FINANCE: 266 разрешений на строительство / 179 застройщиков (178 на эскроу) / 5.65M м²","7) КЛЮЧЕВОЕ: СРЕДНЯЯ СТАВКА ПЕРВИЧКИ в РФ = 6.83% (субсидированная эскроу-ипотека). ВТОРИЧКа 12.95% — это средний реальный кредит (не рыночный 19.59% из mortgage_rates), то есть много льготных категорий (семейная 8%, IT 6% ит.д.)","НЕ СКАЧАНО (5 страниц из 12): housing, housing_dev, realization (поквартирный прайс-лист!), mortgage_rates, stat_series. Требуют page-specific user-interaction triggers. TODO в следующей сессии — расширить 30_scrape_domrf.py interactions (клик на вкладки/фильтры)"]}
{"type":"entity","name":"DomRF_Schema_Relations_Apr26","entityType":"infrastructure","observations":["Дата: 26.04.2026 вечер. Миграция data/sql/40_relations.sql — FK constraints + helper views между всеми таблицами DOM.РФ и Rosreestr на ПРОДЕ","BOOTSTRAP ДЛЯ FK:","• Добавлена region_id=0 ('Российская Федерация' / '_RF') в domrf_regions — этот ID используется как all-Russia placeholder в domrf_flat_area_distribution и domrf_developer_aggregates","• Бэкфилл 22 снапшотов в domrf_snapshots из всех дочерних таблиц с snapshot_date","FK CONSTRAINTS (27 шт):","• 23 × fk_snap_<table>: все domrf_* таблицы с snapshot_date → domrf_snapshots(snapshot_date) ON UPDATE CASCADE","• fk_region_aggregates_region: domrf_region_aggregates.region_id → domrf_regions(region_id)","• fk_flat_area_region: domrf_flat_area_distribution.region_id → domrf_regions(region_id)","• fk_developer_agg_region: domrf_developer_aggregates.region_id → domrf_regions(region_id)","• fk_developer_agg_developer: domrf_developer_aggregates.developer_id → domrf_developers(developer_id)","НЕ ДОБАВЛЯЛ FK (не подходят по типу):","• domrf_launch_top.entity_id — смешанные ID (developer_id TEXT, region_id numeric, area name) в одной TEXT колонке с dim_type-разбивкой","• domrf_sold_ready_breakdown.entity_key — тоже смешанный ключ (название по chartType)","• domrf_commissioning.region_id — ДРУГАЯ система ID (внутренняя НОМЕНКЛАТУРА commissioning API), не совпадает с domrf_regions(region_id)","• rosreestr_deals.region_code — SMALLINT в partitioned table; по значениям совпадает с domrf_regions.region_id, но формальный FK на partitioned-table сложен — JOIN с v_rosreestr_market_by_region","HELPER VIEWS (4 шт):","• v_region_master — ОДНА строка на регион со всеми ключевыми метриками: квартирография (DOM.РФ) + распроданность (PDF и API) + проектное финансирование + 214-ФЗ + запуски/ввод","• v_developer_master — Профиль застройщика: реестр + квартирография по комнатностям + запуски/ввод + распроданность. PRINZIP, Брусника, ЛСР и др. в одном выборке","• v_rosreestr_market_by_region — Цены сделок Росреестра (median/p10/p90 ₽/м²) по кварталам с DOM.РФ-именами регионов и ФО (только квартиры)","• v_market_pulse_rf — ОДНА СТРОКА: РФ pulse: 118.7M м² стр-ва, продано 30.91%, рыночная ставка 19.9% vs реальная 6.83% (разница 13 пп — субсидии), 68 714 кредитов на 290 млрд ₽, средняя цена 216 316 ₽/м²","КЛЮЧЕВЫЕ ИНСАЙТЫ ИЗ v_developer_master для PRINZIP вс конкуренты Свердл.обл:","• Брусника 30 106 квартир / 1 780 тыс м² / доля РФ 1.49% / sold% 46.6%","• ЛСР 33 933 / 1 270 / 1.07% / sold 48.1%","• КОРТРОС 9 815 / 484 / 0.41% / sold 28.4%","• Атомстройкомплекс 4 018 / 233 / 0.20% / sold 15.0% (ОЧЕНЬ МЕДЛЕННО ПРОДАЁТ)","• УГМК 1 883 / 138 / 0.12% / sold 41.5%","• Стройтэк 1 515 / 77 / 0.06% / sold 28.4%","• PRINZIP 814 / 31 / 0.026% / sold 48.4% (БЫСТРО ПРОДАЁТ!)","PRINZIP имеет НАИВЫСШИЙ sold_pct (48.4%) среди сравнимых застройщиков Свердл.обл. Несмотря на маленький портфель (814 кв-р), 75% однушки с хорошей absorption rate — продукт попадает в рыночный спрос ЛУЧШЕ чем КОРТРОС/Атомстройкомплекс с большими портфелями"]}
{"type":"entity","name":"Session_End_Apr26_2026","entityType":"event","observations":["Дата: 26.04.2026 поздний вечер. Итоги дня перед чисткой контекста. При продолжении работы читай СНАЧАЛА DB_Schema_Final_Apr26 + эту сущность.","СДЕЛАНО ЗА ДЕНЬ (4 крупных вехи):","1) Rosreestr CSV сделок залит на прод — 7 кварталов (2024Q3-2026Q1), 7.58M сделок РФ, 296K Свердл.обл. См. Rosreestr_DealsCSV_Loaded_Prod_Apr26.","2) ДОМ.РФ JSON dashboard залит (89 регионов, 2734 застройщика, 11K рядов агрегатов). См. DomRF_Analytics_Loaded_Prod_Apr26.","3) 7 XLSX/PDF с юзер-выгрузки (developer_rf, escrow_rf, guaranty, housing_info, sold_out_info, mortgage_rates, Квартирография). См. DomRF_XLSX_PDF_Snapshot_Loaded_Apr26.","4) Playwright headless scraper написан и запущен — скачал 7/12 страниц ДОМ.РФ через ServicePipe WAF. 64 JSON-файла → 10 новых нормализованных таблиц. См. DomRF_Playwright_Scraper_Apr26 + DomRF_Scraped_Loaded_Prod_Apr26.","+ FK constraints + 4 helper views поверх всех таблиц. См. DomRF_Schema_Relations_Apr26.","СОСТОЯНИЕ ПРОД-БД (gendsgn.ru / 46.173.16.127):","• PostgreSQL 16 + PostGIS 3.4 в docker-compose. Размер 1855 MB.","• 36 таблиц + 4 view + 3 mat view + 7 партиций + 28 FK.","• Доступ только через SSH-туннель (порт 5432 бинд на 127.0.0.1).","• Локальный порт после туннеля у юзера: 15432 (прод), 5432 (был локальный).","• Пароль POSTGRES_PASSWORD: 2J2SBPMKuS998fiwhtQqDhMI (светился в чате несколько раз — юзер может сменить через docker compose recreate postgres).","• БД: gendesign, Юзер: gendesign.","ДОСТУП К ПРОДУ:","• SSH-ключ: C:\\Users\\user\\.ssh\\gendesign_deploy (и копия в sshkey.txt в корне репо — юзер разрешил)","• SSH config alias: 'gendesign' → 46.173.16.127 с LocalForward 15432:5432 и 8000:8000","• Команда: ssh gendesign (или ssh -N gendesign для только туннеля)","• Инструкция для Mac: скопировать ключ в ~/.ssh/, добавить тот же ssh config block, подключаться через TablePlus/DBeaver на localhost:15432","TODO СЛЕДУЮЩЕЙ СЕССИИ (по важности):","• 5 страниц ДОМ.РФ не скачались (lazy-load с user-interaction): housing, housing_dev, realization (ПОКВАРТИРНЫЙ ПРАЙС!), mortgage_rates, stat_series. Расширить data/sql/30_scrape_domrf.py page-specific click triggers.","• /сервисы/api/kn/flats?regions=66&developers=6208_0 — поквартирный прайс-лист PRINZIP, Authorization: Basic MTpqd2U=. Идеальный источник для вкладки Prinzip.","• NSPD GeoJSON кадастровых кварталов Свердл.обл → таблица cadastral_quarters PostGIS для spatial join.","• Cron quarterly_rosreestr_sync на VPS (16-го числа 2-го месяца после квартала).","• Cron domrf_daily_scrape на VPS (Playwright + chromium 300 MB).","• FastAPI router /api/v1/analytics/{ural|ekb|prinzip} используя v_region_master / v_developer_master / v_market_pulse_rf.","• Alembic-миграции из *.sql (воспроизводимость при wipe).","• Пользователь спрашивал 'можно ли объединить дублирующие таблицы' — НЕ ОТВЕЧЕНО, вернуться в следующей сессии. Кандидаты на объединение: domrf_sold_out (PDF, 9 рядов) vs domrf_sold_ready_breakdown (API, 2660 рядов) — покрывают одну тему; domrf_developers (справочник, 2734) vs domrf_developers_full (реестр с метриками, 2563) — разные но перекрываются; domrf_planned_commissioning vs domrf_commissioning vs domrf_launch_monthly — все про ввод.","ОГРАНИЧЕНИЯ КОТОРЫЕ СТОИТ ПОМНИТЬ:","• PRINZIP id = '6208_0', в базе как developer_id TEXT, найдёшь в v_developer_master.","• Свердл.обл region_id = 66 в domrf_regions И region_code = 66 в rosreestr_deals — системы КОДОВ совпадают (Rosstat-style коды).","• ДДУ-данные Свердл.обл в Rosreestr CSV НЕПОЛНЫЕ до середины 2025 (Q1 2025 = 2 сделки — lag публикации). С Q2 2025 нормально.","• Средняя цена МКД РФ от ДОМ.РФ = 216 316 ₽/м² (sold_out PDF). Первичка Свердл.обл median из Росреестра = 149 377 ₽/м² (Q1 2026, ДДУ). Это НОРМАЛЬНО — средняя РФ выше из-за Москвы/Питера.","• 5 страниц из 12 ДОМ.РФ не скачались — это НЕ ошибка скрейпера, это фича lazy-loading. Нужны page-specific click triggers.","КЛЮЧЕВЫЕ ИНСАЙТЫ ДНЯ НАПОМНИТЬ:","• PRINZIP с мини-портфелем (814 кв-р) имеет НАИВЫСШИЙ sold_pct 48.4% среди сравнимых застройщиков Свердл.обл. Атомстройкомплекс в 4× больше sold_pct 15%.","• Резкое падение ввода после 2028 года: 2026=37.9M→ 2027=35.4→2028=26.5→2029=11.0→2030=4.3M м². Окно Discovery MVP именно сейчас.","• Средняя фактическая ставка первички РФ 6.83% (субсидии), но рыночная 19.9% — разница 13 пп это субсидирование госпрограмм.","• Комфорт = 67% всех запусков РФ (6.93M м² из 10.56M total). Типовой всего 19%.","• Сбер доминирует эскроу: 72.8M м² = 61% всего эскроу-рынка.","• Свердл.обл рынок: 5.67M м² в стройке, 179 застройщиков, sold_pct 29% (хуже среднего РФ 31%) но soldReady_pct 80% (здоровый баланс стройки/продаж).","СТРУКТУРА РЕПО для этой работы: data/sql/ — 9 SQL/PY скриптов, data/raw/ — 1 GB CSV+JSON (в .gitignore). Граф связей обновлён — ~150 связей, все ключевые entities связаны с Project_GenDesign и PlanA_AnalyticsFirst_Apr25."]}
{"type":"entity","name":"DomRF_History_Loaded_Apr27_2026","entityType":"event","observations":["Дата: 27.04.2026 поздний вечер. ДОГРУЖЕНА ИСТОРИЯ 14 месяцев (12 мес 2025 + Январь/Февраль 2026) для realization + sold_ready эндпоинтов ДОМ.РФ.","АРТЕФАКТЫ: data/sql/40_scrape_history.py + 41_load_history.py + 42_schema_breakdown_widen.sql.","ПОДХОД: API DOM.РФ принимает исторические repYear/repMonth параметры — подтверждено пробой. Для каждого месяца SNAPSHOT_DATE = последний день периода (2025-01-31, 2025-02-28, ...) — против конфликтов PK.","СКРЕЙП: 6 755 JSON-файлов / 14 месяцев / ~480 файлов на месяц. data/raw/domrf_history/{realization,sold_ready}/<YYYY-MM>/. Работал ~17 минут (Playwright headless Chromium, 89 регионов × 4 endpoint × 14 мес ≈ 5K fetch).","ЗАЛИТО В ПРОД:","• domrf_realization — было 9 747, стало 143 963 (+134 216 рядов, 14 новых snapshot_date'ов).","• domrf_sold_ready_index — +14 рядов (по ОДНОМУ ряду НА месяц: РФ-итог: squareSum / soldPerc / readyPerc / soldReadyPerc).","• domrf_sold_ready_breakdown — +37 384 рядов (7 chart_type × ~2 600 × 14 мес). Chart types: foChart (9), regionChart (89), devChart (~2 700-3 500 зависимо от периода), devValueChart (5 бакетов), cityPopulationChart (4), classChart (4), readyYearChart (~7).","• domrf_sold_ready_dynamics — +3 150 рядов (4 dynamic_chart_type × × годы × месяцы 2020-period).","• domrf_snapshots — +14 рядов (snapshot_date'ов истории), всего стало 18.","SCHEMA ИЗМЕНЕНИЕ (42_schema_breakdown_widen.sql):","Было: domrf_sold_ready_breakdown.extra JSONB с любыми лишними полями (foCd в своей колонке, остальные в JSONB). Стало: 6 типизированных колонок, JSONB дропнут. Каждый chart_type имеет одно дискриминаторное поле:","• foChart → fo_cd (INT, 100-108)","• regionChart → region_cd (INT, Rosstat 1-95)","• devChart → dev_calc_group_id (TEXT, '5791_0' = Брусника, '6072_0' = Самолёт, '6208_0' = PRINZIP)","• devValueChart → dev_group_value (TEXT, do10/do25/do50/do100/over100 бакеты размера)","• cityPopulationChart → city_population (TEXT, do50/do100/do250/over1000 население)","• classChart → obj_class (TEXT, typical/comfort/business/elite)","• readyYearChart → ready_year (INT, год планируемой готовности)","COMMENT добавлен на каждую новую колонку.","КЛЮЧЕВЫЕ INSIGHTS ИЗ ИСТОРИИ:","• Свердл.обл realization total: объём стр-ва рос 5 115 (Янв 2025) → 6 015 (Дек 2025) тыс м² (+18% за год), затем откат в 5 686 (Мар 2026, -5%). Цена выросла 136 796 → 151 397 ₽/м² (+11%).","• sold_perc Свердл.обл: 35% (Янв 2025) → 29% (Мар 2026). Рынок остывает.","• Брусника (developer_id 5791_0) sold% timeseries: 33% (Mar 2025) → 50.36% (Feb 2026). РЕКОРДНЫЙ РОСТ велосити среди крупных девелоперов РФ — Свердл.обл портфель лучше продаётся в сравнении с Самолётом (sold% в районе 36-40% константно). PRINZIP обгоняет обоих в Свердл.обл 47-48%.","ОГРАНИЧЕНИЯ / TODO:","• escrow история НЕ догружена — endpoint /portal-analytics/api/escrow?date=01-XX-2025 вернул 404/403 при пробе (WAF временное или URL другой). escrow_allDate.json показывает что данные есть вся история. Отдельный TODO — добраться правильным путем.","• launch / commissioning / mortgage_stats / quartirografia / housing/_dev / project_finance — НЕ перескрейпливали за 2025: их существующие endpoints возвращают timeseries 2020-2026 в ОДНОМ ответе (видно в launch_monthly: 75 рядов = 5 лет × 12 мес + 15 мес 2026; commissioning, sold_ready_dynamics то же самое).","• stat_series уже имел 2020-2026 из XLSX, не трогали.","• ПОДНЯТЬ ЯСНОСТЬ С SOLD_READY_DYNAMICS: в 1 месяц = 225 рядов (4 chart_type × годы 2020-period × 12 мес). Разные snapshot_date имеют оверлапы — снапшот июля-2025 репит 2020-01..2025-07, снапшот август-2025 репит 2020-01..2025-08. Это НОРМАЛЬНО — они в PK вместе с snapshot_date.","MCP CONNECTOR ИСПОЛЬЗОВАНИЕ: вся DDL (ALTER TABLE 42), все SELECT-верификации, инфо о схеме делались через mcp__postgres__execute_sql. Питон-скрипты использовались только для парсинга 6755 локальных JSON-файлов и batch INSERT (MCP файлы не парсит).","ДОСТИЖИМО СЕЙЧАС:","• Динамика по региону/девелоперу/классу/размеру портфеля по МЕСЯЦАМ за 14 периодов.","• Анализ 'velocity' различных девелоперов по регионам.","• Ответ на вопрос 'PRINZIP лучше ДК/ФСК/КОРТРОС?' — теперь с трендом.","• Ответ на 'sold% в Свердл.обл растёт или падает?' — ПАДАЕТ 35→29%."]}
{"type":"entity","name":"Sverdl_Quartirography_Report_Apr27","entityType":"research","observations":["Дата: 27.04.2026. ОТЧСТ ПО КВАРТИРОГРАФИИ СВЕРДЛОВСКОЙ ОБЛАСТИ НА ОСНОВЕ ВСЕГО ANALYTICAL ПЛАСТА ДАННЫХ PROD DB.","ИСТОЧНИКИ: domrf_realization (143K rows), rosreestr_deals (4.97M raw, 296K Свердл), domrf_region_aggregates, domrf_developer_aggregates, domrf_kn_objects (1516 ЖК Свердл), ekb_districts, yandex_realty_zk, domrf_sold_ready_breakdown.","РЫНОК СВЕРДЛ 14 МЕС (ЯНВ 2025 - АПР 2026):","• Объём стр-ва: 5 115 → 6 015 тыс м² за 2025 (+18%), затем откат в 5 686 Мар 2026 (-5%).","• sold%: 35% → 29% (-6пп) — рынок охлаждается, unsold вырос 50%→54%.","• Цена: 136 796 → 151 397 ₽/м² (+11% за 14 мес) — МЕДЛЕННЕЕ инфляции и реальной ставки ЦБ 11%.","КВАРТИРОГРАФИЯ СВЕРДЛ ПОРТФЕЛЬ (что строится, 115 205 квартир):","• 1-к: 60 652 (52%) × 36.5 м² ср. — САМЫЙ БОЛЬШОЙ СЕГМЕНТ","• 2-к: 39 839 (35%) × 57.1 м²","• 3-к: 13 754 (12%) × 78.9 м²","• 4+к: 960 (1%) × 103.7 м²","РЕАЛЬНЫЕ ДДУ-СДЕЛКИ СВЕРДЛ Q3 2025-Q1 2026 (Rosreestr 460 сделок с фильтрами):","• Студии 15-30 м²: 87 сделок (19%), медиана 114 557 ₽/м²","• 1-к 30-45 м²: 67 (15%), медиана 112 640 ₽/м²","• 2-к 45-60 м²: 56 (12%), медиана 123 932 ₽/м²","• 3-к 60-80 м²: 36 (8%), медиана 126 934 ₽/м²","• БОЛЬШИЕ 80+ м²: 171 (37%!), медиана 139 382 ₽/м² — ЛИДЕР ПО СДЕЛКАМ, ср. чек 20 М ₽!","ПАРАДОКС: строят 52% однушек, покупают 37% больших 80+ м². Рынок голосует деньгами за семейные квартиры, предложение ориентировано на инвесторский сегмент студий-однушек.","PIPELINE ПО ГОДУ ВВОДА (Свердл, Апр 2026):","• 2026: 1 649 тыс м², sold 54% (запаздывать входить)","• 2027: 1 745, sold 29%","• 2028: 1 567, sold 15%, unopened 19% 🚩","• 2029: 538, sold 4%, unopened 56% 🚩🚩","• 2030: 122, sold 0.2%, unopened 89% 🚩🚩🚩","• 2031: 65, sold 0%, unopened 100%. ОКНО ИНВЕСТИЦИЙ: 2026-2027 ввод.","ТОП-15 ДЕВЕЛОПЕРОВ СВЕРДЛ (sold% динамика 14 мес):","• ПОБЕДИТЕЛИ: PRINZIP +33пп (15→48), Холдинг Форум-групп +21пп (33→54%) — ЛИДЕР ПО SOLD%, Брусника +11пп (36→47), Астра +11пп (19→30), КОРТРОС +4пп, Атлас +5пп.","• ПРОИГРЫВАЮЩИЕ: Унистрой ОБВАЛ 59→8% (-51пп при росте +176 тыс м²), Атомстройкомплекс -31пп (46→15), Эталон -28пп (45→17), УГМК -27пп (69→42). ПАТТЕРН ЗАТОВАРИВАНИЯ.","ТОП ЖК ЕКБ (1 285 ЖК в реестре):","• САМЫЕ БОЛЬШИЕ: ЖК СТАРТ (ТЭН, 1566 кв.), Сибирский сад (Страна Дев, 1429+1142), Основинские Кв-ы (ТЭН, 1224), Первый Академ (КОРТРОС, 1050), Атлас Юник (Атлас, 1044).","КОНЦЕНТРАЦИЯ ПО РАЙОНАМ ЕКБ:","• Академический: 330 ЖК / 82 520 кв-р (ЛИДЕР)","• Ленинский: 215 / 50 754","• Верх-Исетский: 151 / 37 611","• Чкаловский: 142 / 38 506","• Орджоникидзевский: 139 / 28 733","• Железнодорожный: 135 / 30 428","• Кировский: 115 / 29 754","• Октябрьский: 90 / 27 863 (НАИМЕНЬШАЯ КОНКУРЕНЦИЯ)","РЕКОМЕНДАЦИИ (ЧТО СТРОИТЬ):","• Приоритет #1: семейные 60-90 м² (3-к) — дефицит предложения, 8% сделок, ср. чек 10.5 М ₽.","• Приоритет #2: большие 100-150 м² — 37% сделок при Ц 153K ₽/м², ср. чек 20 М ₽. Премиум кад.кварталы: 66:41:0701011 (мед 424K), 66:41:0106113 (172K), 66:41:0704044 (149K).","• ИЗБЕГАТЬ: однушки 30-40 м² (переразвиты), проекты 2028+ на эскроу (66-89% unsold).","ГДЕ СТРОИТЬ: Кировский/Октябрьский (недо-инвестированы), не-ЕКБ города (Н.Тагил 23 ЖК, Первоуральск, Арамиль).","BENCHMARK MODELS: Брусника (350 тыс м² / sold 47% / +11пп), Холдинг Форум-групп (113 тыс м² / sold 54% / +21пп лидер velocity).","РАЗРЫВ СРЕДНЕЙ: Брусника ср. 60 м², Форум ср. 61 м², PRINZIP ср. 38 м² — в 1.5х меньше рынка (49 м²).","YANDEX REALTY ACTIVE LISTINGS (снимок 27.04.2026): в БД всего 12 записей (Comfort 6, Business 4, Comfort+ 1, Elite 1). Предыдущий факт «258 новостроек» был устаревшим снимком. Текущий парсер явно недобирает — режимы являются кандидатом на перевыполнение в ближайшее время."]}
{"type":"entity","name":"PRINZIP_Strategy_Apr27","entityType":"research","observations":["Дата: 27.04.2026. СТРАТЕГИЧЕСКИЙ АНАЛИЗ ДЛЯ PRINZIP (developer_id 6208_0) НА ОСНОВЕ PROD ДАННЫХ.","ТЕКУЩИЙ ПОРТФЕЛЬ (developer_aggregates):","• ВСЕГО: 814 квартир / 31 040 м² / 28 ЖК / ср. 38.1 м²","• 1-к: 614 (75% портфеля) × 30.8 м² — ОЧЕНЬ МАЛЕНЬКИЕ","• 2-к: 156 (19%) × 52.8 м²","• 3-к: 22 (3%) × 81.3 м²","• 4+к: 22 (3%) × 95.2 м²","ПОРТФЕЛЬ ПО СТАТУСУ: 26 из 28 ЖК СДАНЫ (2018-2024). СТРОЙКА: Шарташ Парк (523 кв, сдача 2026-12, эскроу) + 2-я очередь Парк Победы (291, 2027-03).","VELOCITY ЛИДЕРСТВО: sold% 15% (Янв 2025) → 48% (Апр 2026) = +33пп. ЛУЧШИЙ РОСТ СРЕДИ ТОП-5 СВЕРДЛ (Брусника +11, Форум +21, KORTROS +4, Атлас +5). Объём НЕ растёт (стабильно 31 тыс м²).","ГЕОГРАФИЯ PRINZIP ПО РАЙОНАМ ЕКБ:","• Октябрьский: 6 ЖК / ДОЛЯ РАЙОНА 6.7% (высокая концентрация, парковый квартал/Ленина/LVIII)","• Верх-Исетский: 4 ЖК / доля 2.6% (Первый Николаевский, Малевич)","• Ленинский: 4 ЖК / 1.9% (Ньютон Парк, Краснолесья)","• Кировский: 2 ЖК / 1.7% (Первомайская 60, Шарташ)","• Орджоникидзевский: 1 ЖК / 0.7% (Парк Победы/Татлин 3 объекта)","• АКАДЕМИЧЕСКИЙ: 0 PRINZIP / 0% (САМЫЙ БОЛЬШОЙ КЛАСТЕР 330 ЖК / 82К квартир — PRINZIP ОТСУТСТВУЕТ 🚨)","• Чкаловский: 0 / 0% (142 ЖК / 38К кв.)","• Железнодорожный: 0 / 0% (135 ЖК / 30К)","КЛЮЧЕВОЙ РАЗРЫВ С РЫНКОМ:","• PRINZIP средняя квартира 38 м² vs Свердл 49 м² vs Брусника 60 м² vs Форум 61 м².","• PRINZIP доля 1-к 75% vs Свердл 52% vs Брусника 47%.","• PRINZIP доля 3-к+ всего 6% vs Свердл 13% vs Брусника 18% vs Форум 21%.","ПОРТФЕЛЬ PRINZIP ОРИЕНТИРОВАН НА ИНВЕСТОРОВ / МОЛОДЫХ ПОКУПАТЕЛЕЙ, НО РЫНОК СЕЙЧАС ПОКУПАЕТ СЕМЕЙНЫЙ 80+ м².","PRINZIP CRM данные (из Антона): средний чек 2025 = 6.15 М ₽, conversion 5.4% (обвал с 11.2% в 2020). 39.9 млрд ₽ revenue за 8 лет. Пик 2023 (12.81% conv).","РЕКОМЕНДАЦИИ СТРАТЕГИИ PRINZIP:","ПРИОРИТЕТ #1: семейные квартиры 60-90 м² (3-к). Дефицит в портфеле (3% vs Брусника 17%), ср. чек 10.5 М ₽. Подъём среднего чека выше текущего CRM 6.15 М.","ПРИОРИТЕТ #2: премиум 100-150 м² (37% сделок, 20 М ₽). Кад.кварталы 66:41:0701011 (МЕД 424K!), 66:41:0106113 (172K), 66:41:0704044 (149K). Расширить Парковый Кв-л/LVIII модель.","ГДЕ СТРОИТЬ НОВОЕ:","• #1 АКАДЕМИЧЕСКИЙ (330 ЖК, 0% PRINZIP) — самый большой кластер ЕКБ, ПРИНЦИП ИГНОРИРУЕТ. Семейный сегмент молодых покупателей.","• #2 ВЕРХ-ИСЕТСКИЙ расширение — кад.квартал 66:41:0106113 (ср. 113 м² × 172K ₽/м²). Бизнес 80-130 м².","• #3 ЧКАЛОВСКИЙ / ЖЕЛЕЗНОДОРОЖНЫЙ — растущие районы, 0% PRINZIP, низкая конкуренция. Тест 60-80 м² без премиума.","НЕ РАСШИРЯТЬ: Октябрьский (уже 6.7% доля), Орджоникидзевский (выросли из Парка Победы).","ОБЩАЯ СТРАТЕГИЯ: 'Брусника model' в Академическом + 'Премиум-проект 80-150 м²' в Верх-Исетском. Сократить 1-к с 75% до 50%, увеличить 3-к+ с 6% до 20%. Удержать sold% > 45% — ваше преимущество."]}
{"type":"entity","name":"Schema_Tables_Map_Apr27","entityType":"infrastructure","observations":["1⃣ DOM.РФ realization & history (4): domrf_realization, domrf_sold_ready_index, domrf_sold_ready_breakdown, domrf_sold_ready_dynamics","2⃣ DOM.РФ stat_series (3): domrf_stat_series_observations, domrf_stat_series_indicators, domrf_xlsx_files","3⃣ DOM.РФ JSON dashboard (3): domrf_region_aggregates, domrf_developer_aggregates, domrf_flat_area_distribution","4⃣ DOM.РФ XLSX/PDF (8): domrf_developers, domrf_developers_full, domrf_escrow_banks, domrf_guaranty_regions, domrf_housing_summary, domrf_planned_commissioning, domrf_sold_out, domrf_mortgage_rates","5⃣ DOM.РФ launch/commissioning (5): domrf_launch_top, domrf_launch_obj_class, domrf_launch_monthly, domrf_commissioning, domrf_project_finance","6⃣ DOM.РФ ipoteka (2): domrf_mortgage_dashboard, domrf_mortgage_details","7⃣ DOM.РФ kn-API (2): domrf_kn_flats, domrf_kn_objects","8⃣ DOM.РФ growth (1): domrf_dev_growth","9⃣ DOM.РФ raw (1): domrf_raw_endpoints","🔟 DOM.РФ dimensions (4): domrf_regions, domrf_snapshots, domrf_federal_districts, domrf_territory_aliases","1⃣1⃣ ЦБ ипотека (2): cbr_mortgage_series, cbr_mortgage_files","1⃣2⃣ Внешние данные (3): sber_ddf_metrics, yandex_realty_zk, yandex_realty_class_prices","1⃣3⃣ Geo Свердл/ЕКБ (4): ekb_districts, ekb_metro, sv_cities, sv_dev_sales","1⃣4⃣ Rosreestr (10): rosreestr_deals + 7 partitions (2024Q3..2026Q1) + rosreestr_deals_staging + rosreestr_rent_deals","1⃣5⃣ PostGIS system (1): spatial_ref_sys","САМЫЕ БОЛЬШИЕ ПО РАЗМЕРУ: rosreestr_deals_2024q4 (253MB), domrf_stat_series_observations (254MB), rosreestr_deals_2024q3 (237MB), domrf_realization (39MB), domrf_sold_ready_breakdown (11MB), domrf_kn_flats (7.4MB).","ОБНОВЛЕНО 27.04.2026 поздний вечер: 59 public TABLES (было 53), 1 871 MB после vacuum/repack (было 2 177 MB).","7⃣ DOM.РФ kn-API РАСШИРЕНО (8): domrf_kn_flats, domrf_kn_objects, domrf_kn_sale_graph (time-series продаж), domrf_kn_sales_agg (текущие агрегаты 3 типа), domrf_kn_infrastructure (норм POI), domrf_kn_photos (мета+local_path), kn_scrape_runs (журнал прогонов), kn_scrape_failures (per-request ошибки с full_url для ручной проверки в браузере).","Рост от 53 до 59: +6 таблиц из экстрас-скрейпера (DomRf_Kn_Scraper_Apr27).","+4 PRINZIP CRM таблицы/views (пока пустые, ждут SQLite-файл): prinzip_leads, prinzip_deals, prinzip_funnel_monthly (MV), prinzip_funnel_by_object (MV). Общее количество таблиц +2 (leads/deals без MV)."]}
{"type":"entity","name":"Schema_FK_Map_Apr27","entityType":"infrastructure","observations":["СНАПШОТ 27.04.2026. 35 FK constraints по parent table.","domrf_snapshots (24 child FKs) — все таблицы со snapshot_date: commissioning, developer_aggregates, developers_full, escrow_banks, flat_area_distribution, guaranty_regions, housing_summary, launch_monthly, launch_obj_class, launch_top, mortgage_dashboard, mortgage_details, mortgage_rates, planned_commissioning, project_finance, raw_endpoints, region_aggregates, sold_out, sold_ready_breakdown, sold_ready_dynamics, sold_ready_index, realization ⭐, xlsx_files ⭐, stat_series_observations ⭐.","domrf_regions (5 child FKs): developer_aggregates, flat_area_distribution, region_aggregates, realization (region_code) ⭐, kn_objects (region_cd) ⭐, rent_deals (region_cd) ⭐, territory_aliases.","domrf_developers (3 child FKs): developer_aggregates, kn_objects (dev_id) ⭐, sv_dev_sales (dev_id) ⭐.","domrf_federal_districts (1 child FK): territory_aliases.","ЭВОЛЮЦИЯ: 26.04 было 28 FK → 27.04 lazy +3 → 27.04 territory aliases +2 → 27.04 relations v2 +4 = 35 итого.","НЕ СОЗДАНЫ (data quality issues):","• domrf_kn_flats.obj_id → kn_objects: разные ID-системы API, 27563 orphans.","• domrf_kn_flats.region_cd — все NULL.","• dev_growth.dev_id — все NULL.","• realization.subject (для endpoint_type=developer) → developers — partial constraint нельзя выразить стандартным FK (subject overloaded для total/housing/ready_year).","ОРИГИНАЛ: data/sql/40_relations.sql (базовые 28 FK) + 38_relations_fix.sql (+4 для realization/xlsx/stats) + 39_territory_aliases.sql (+2) + 45_relations_v2.sql (+4 kn_obj/dev_sales/rent). Индексы на FK childs авто."]}
{"type":"entity","name":"Schema_Views_Catalogue_Apr27","entityType":"infrastructure","observations":["9 helper views в prod-БД на 27.04.2026.","BASE (legacy 26.04, data/sql/40_relations.sql):","• v_market_pulse_rf — ОДИН ряд РФ-метрики: 118.7M м² стр-ва, sold 30.91%, Ц 216 316 ₽/м², рыночная ипотека 19.9% vs реальная 6.83%.","• v_developer_master — профиль девелопера из sold_ready breakdown + aggregates (ЛЕГАСИ, заменён v_developer_full_metrics).","• v_region_master — один ряд на регион: квартирография + sold_out + sold_ready + project_finance + guaranty + launch.","• v_rosreestr_market_by_region — Rosreestr p10/median/p90 + DOM.РФ имена.","TERRITORY (39_territory_aliases.sql):","• v_stat_series_resolved — stat_series_observations LEFT JOIN aliases LEFT JOIN indicators. Резолвит 99 вариативных имён территорий. WHERE region_id=66 → Свердл.","RELATIONS V2 (45_relations_v2.sql):","• v_jk_with_developer — ЖК + canonical dev_name + region_name (FK kn_obj→developers/regions).","• v_jk_sales_summary — flats GROUP BY obj_name: total/sold/booked/free + sold_pct + avg_ppm + total_value.","• v_developer_portfolio — девелопер + все его ЖК/корпуса (count/flats/sqm + ekb/escrow/completed/in_progress).","• v_developer_full_metrics — ⭐ ULTIMATE: portfolio + квартирография долей (1к/2к/3к/4+) + realization Свердл sold%/цена. PRINZIP/Брусника/Форум-групп всё видно одним запросом."]}
{"type":"entity","name":"Schema_ETL_Artefacts_Apr27","entityType":"infrastructure","observations":["Эволюция data/sql/ с 26.04.2026 по 27.04.2026.","26.04 база (16 файлов):","• 01_schema_rosreestr_deals.sql, 02_load_all_quarters.sh, 03_materialized_views.sql","• 10_schema_domrf.sql, 11_load_domrf.py","• 20_schema_domrf_extras.sql, 21_load_domrf_extras.py","• 30_scrape_domrf.py (Playwright headless Chromium WAF-bypass)","• 31_schema_domrf_full.sql, 31_schema_domrf_raw.sql","• 32_load_domrf_full.py, 32_load_domrf_raw.py","• 40_relations.sql (FK + 4 helper views)","27.04 новые 9 файлов:","• 33_schema_domrf_lazy.sql + 34_load_domrf_lazy.py — realization/xlsx_files/raw_endpoints (5 lazy-load страниц)","• 35_schema_domrf_stats.sql + 36_parse_xlsx_stats.py — long-form panel из 7 XLSX (809K observations)","• 37_cleanup_redundant.sql — DROP sold_out_by_year/by_progress (дубли realization)","• 38_relations_fix.sql — +4 FK на snapshots, region_code -1→0 migration, drop dup indexes, COMMENT'ы","• 39_territory_aliases.sql — federal_districts(8) + territory_aliases(101) + v_stat_series_resolved","• 40_scrape_history.py + 41_load_history.py — 14 мес history (2025+Янв/Февр 2026)","• 42_schema_breakdown_widen.sql — sold_ready_breakdown JSONB extra → 6 типизированных колонок","• 43_anton_import.sql + 44_import_anton_db.py — импорт Антоновской SQLite (13 таблиц + merge developers)","• 45_relations_v2.sql — +4 FK kn_obj→regions/developers, sv_dev_sales→developers, rent_deals→regions + 4 analytical views (jk_with_developer, jk_sales_summary, developer_portfolio, developer_full_metrics)","НАИМЕНОВАНИЕ CONVENTION: NN_action_target.{sql|py|sh}. NN — порядок и группировка (00s rosreestr, 10s dashboard, 20s xlsx, 30s scrape+full, 40s relations+history, 45+ recent updates)."]}
{"type":"entity","name":"Schema_Open_TODOs_Apr27","entityType":"feedback","observations":["TODO работ над аналитическим пластом НА 27.04.2026 вечер (синхронизировано с DB_Schema_Final_Apr26).","ДОПОЛНИТЕЛЬНЫЕ ИСТОЧНИКИ ДАННЫХ:","• PRINZIP CRM (49 MB SQLite на analytics.prinzipevent.ru) — 102K заявок, 9K сделок, 39.9 млрд ₽ revenue за 8 лет. user подтвердил доступ — отдельный пасс импорта.","• Rosreestr архив 2000-2021 (6.7M сделок Свердл). У Антона _rosreestr_sv_deals.json (73 MB).","• escrow исторические даты — пробы 404 на /portal-analytics/api/escrow?date=01-XX-2025. История есть (escrow_allDate.json), нужен правильный URL.","НОРМАЛИЗАЦИЯ СУЩЕСТВУЮЩИХ ДАННЫХ:","• Парсер 01_05_*.xlsx 'Сводный' формат (лежит в xlsx_files BYTEA, bespoke layout).","• Парсер __NEXT_DATA__ для housing_dev/mortgage_rates SSR-блобов (лежат в raw_endpoints).","• GROUP BY comm_name в v_developer_portfolio для реального числа жилых комплексов (сейчас считает корпуса).","ИНФРА:","• Cron quarterly Rosreestr sync (16-го числа 2-го месяца после квартала).","• Alembic-миграции из *.sql файлов (воспроизводимость).","ANALYTICS-ОТЧСТЫ:","• Расширить расчёт среднего чека по классу/району/девелоперу.","• Соединить ЦБ ипотеку (cbr_mortgage_series) с realization sold% — видны ли корреляции.","• Анализ NSPD GeoJSON кадастровых кварталов + spatial join с rr_agg_cad_quarter.","СДЕЛАНО 27.04 вечер (было в TODO):","✅ PRINZIP-флаты probe (TODO #1 из Schema_Open_TODOs) — выгружены 826 квартир PRINZIP через собственный скрейпер (run_id=2). См. DomRf_Kn_Scraper_Apr27.","✅ FastAPI router /api/v1/analytics — 11 endpoints, 3 страницы дашборда. См. Analytics_Dashboard_Apr27.","✅ Фото-рендеры ЖК — метаданные собираются в domrf_kn_photos (5150 рядов по PRINZIP). Binary довыгрузка через --download-photos опционально.","✅ Cron domrf_daily_scrape на VPS — Celery beat + worker в docker-compose.yml. Расписание через SCRAPE_KN_CRON env (default '15 4 * * mon' + jitter 0-30мин).","ОСТАЛОСЬ (open):","• Импорт PRINZIP CRM 49 MB SQLite — выделен в GitHub issue #14.","• Rosreestr архив 2000-2021 (6.7M сделок Sverdl) у Антона.","• escrow исторические даты — нужен правильный URL.","• Парсер __NEXT_DATA__ для housing_dev/mortgage_rates SSR-блобов.","• GROUP BY comm_name в v_developer_portfolio.","• Расширить kn-scraper на 442 строящихся Свердл жК (GitHub #13).","• API endpoints /api/v1/analytics/object/{id}/sale_graph и др. (GitHub #15).","• Multi-target Dockerfile (-200 МБ backend) (GitHub #16).","GitHub backlog: источник правды для operational issues — https://github.com/lekss361/-gendesign/issues. Из открытых: #3 pg_dump → S3, #4 Sentry release, #5-9 Stage 1/2 generative & site-finder, #11 Anton onboarding, #13-16 из этой сессии. #10 (Plan A vs Original) закрыт — решено в пользу analytics-first."]}
{"type":"entity","name":"Sverdl_Market_Trend_Apr27","entityType":"research","observations":["КЛЮЧЕВОЙ ТРЕНД Свердл 14 мес (Янв 2025 - Апр 2026) из domrf_realization timeseries.","ОБЪЁМ СТР-ВА: 5 115 → 6 015 тыс м² (+18% за 2025) → 5 686 (Мар 2026, -5% откат от декабря).","SOLD%: 35% (Янв 2025) → ПЛАТО 32-35% в середине 2025 → 31% (Дек) → 29% (Апр 2026). ОПОСРЕДОВАННОЕ ОХЛАЖДЕНИЕ.","UNSOLD%: 50% → 54% (+4пп). Растёт запас нереализованного.","UNOPENED%: 15% → 17% (вырос лето 2025-2026 до 20% в Дек). Продажи не открываются позже.","ЦЕНА: 136 796 → 151 397 ₽/м² (+11% за 14 мес). МЕДЛЕННЕЕ инфляции и ставки ЦБ 11%. Девелоперы СДЕРЖИВАЮТ рост цен чтобы зажечь спрос.","PIPELINE ПО ГОДУ ВВОДА: 2026 sold 54% → 2027 29% → 2028 15% → 2029 4% → 2030 0.2%. ОКНО ИНВЕСТ: ввод 2026-2027.","REPRO QUERY: SELECT TO_CHAR(snapshot_date,'YYYY-MM'), total_square, sold_perc, price_avg FROM domrf_realization WHERE region_code=66 AND endpoint_type='total' AND type_square='total' ORDER BY snapshot_date;"]}
{"type":"entity","name":"Competitor_Benchmark_Brusnika_Apr27","entityType":"research","observations":["Брусника (developer_id 5791_0) — BENCHMARK для PRINZIP. Средний-крупный portfolio + растущий sold%.","ПОРТФЕЛЬ (developer_aggregates РФ-итог): 30 106 кв-р / 1.80M м² / ср. 60 м².","КВАРТИРОГРАФИЯ: 1к 47%, 2к 35%, 3к 17%, 4+к 1% — СБАЛАНСИРОВАННО семейный профиль.","СВЕРДЛ: 352 тыс м², sold% 47% (Апр 2026). Динамика: 36% (Янв 2025) → 64% (Дек 2025 ПИК) → 47% (Апр 2026 после приёма новых проектов).","КОРПУСОВ (kn_objects.dev_id=5791_0): 45 жилых комплексов, 28 сданы, 17 строятся.","ЧТО ПОДРАЖАТЬ PRINZIP'у: баланс квартирографии (1к/2к/3к 47/35/17 vs PRINZIP 75/19/3), работа с эскроу-проектами (Брусника 17 строит крупно), рост портфеля без потери sold% (Q4 2025 был 64%).","REPRO: SELECT * FROM v_developer_full_metrics WHERE developer_id='5791_0';"]}
{"type":"entity","name":"Competitor_Benchmark_ForumGroup_Apr27","entityType":"research","observations":["Холдинг Форум-групп (developer_id 5832_0) — БЕЗУСЛОВНЫЙ ЛИДЕР VELOCITY Свердл 27.04.","ПОРТФЕЛЬ (РФ-итог): 1 850 кв-р / 113 тыс м² / ср. 61 м².","КВАРТИРОГРАФИЯ: 1к 44%, 2к 34%, 3к 18%, 4+к 3% — ближе всех к 'family balanced' от рыночного спроса.","СВЕРДЛ: 113 тыс м² (мини-портфель относительно лидеров), sold% ЛИДЕР 54% (Апр 2026). Динамика: 33% (Янв 2025) → 47% (Дек) → 54% (Апр 2026) = +21пп за год.","КОРПУСОВ (kn_objects): 44, 34 сданы, 10 строятся.","ОСОБЕННОСТИ: НЕ РОС портфель за 14 мес (113 тыс м² стабильно), выиграл велосити без расширения. МОДЕЛЬ 'ДОПРОДАТЬ ЧТО ЕСТЬ ПРИ РОСТЕ ЦЕН НА НЕПРОДАННОЕ' — ближайшая к PRINZIP.","ЧТО ПОДРАЖАТЬ: PRINZIP имеет ту же логику (не растут объёмы с 31 тыс м²), но благодаря меньшей квартирографии идёт медленнее (PRINZIP +33пп vs Форум +21пп, но Форум выше absolute 54% vs PRINZIP 48%). ПОДНЯТЬ средний м² в портфеле — выравняться с Форумом.","REPRO: SELECT * FROM v_developer_full_metrics WHERE developer_id='5832_0';"]}
{"type":"entity","name":"DomRF_Lazy_Loaded_Apr27_2026","entityType":"event","observations":["Дата: 27.04.2026. ВЕХА: догружены 5 lazy-load страниц ДОМ.РФ + распарсены stat_series XLSX + дропнуты дубли + созданы territory aliases.","СКРЕЙПЕР 30_scrape_domrf.py расширен per-page direct-API триггерами (trigger_housing/_dev/realization/mortgage_rates/stat_series). Внутри page.evaluate(fetch()) — куки/WAF из chromium-context.","5 СТРАНИЦ ИСТОЧНИКИ: housing (302 JSON, /portal-analytics/api/dashboard/*), housing_dev (SSR __NEXT_DATA__), realization (501 JSON, /аналитика/api/rpp/*) ОСНОВНОЙ, mortgage_rates (SSR), stat_series (9 XLSX через fetch+arrayBuffer→base64).","ДОБАВЛЕНО В ПРОД (6 новых таблиц): domrf_realization (9 747), domrf_xlsx_files (9 BYTEA), domrf_stat_series_observations (809 236), domrf_stat_series_indicators (123), domrf_federal_districts (8), domrf_territory_aliases (101). + 333 raw JSONB endpoints в domrf_raw_endpoints.","ДРОПНУТЫ 2 ДУБЛЯ: domrf_sold_out_by_year (покрывался realization endpoint=ready_year) + domrf_sold_out_by_progress (покрывался endpoint=housing). domrf_sold_out ОСТАВЛЕН ради attracted_funds_mln_rub.","FK АУДИТ: добавлены 4 FK (на snapshots+regions), мигрирован region_code -1→0 (2742 ряда), дропнуты 2 дублирующих индекса. Детали в Schema_FK_Map_Apr27.","TERRITORY ALIASES: 101 alias resolver text→(level, region_id|fo_id) + view v_stat_series_resolved. 100% coverage 809K observations stat_series. Детали в Schema_Views_Catalogue_Apr27.","MCP postgres-mcp ПОДКЛЮЧЕН (.mcp.json в project root, .gitignore). С этого момента все DDL/SELECT через mcp__postgres__execute_sql.","ОГРАНИЧЕНИЯ: housing_dev/mortgage_rates SSR-блобы лежат в raw_endpoints (НЕ нормализованы). 2 XLSX 01_05_*.xlsx 'Сводный' формат остаются в xlsx_files BYTEA. См. Schema_Open_TODOs_Apr27.","АРТЕФАКТЫ: data/sql/30_scrape_domrf.py + 33-39_*.sql/py (10 файлов). Список в Schema_ETL_Artefacts_Apr27.","REPRO для Свердлобл realization sold% timeseries: SELECT TO_CHAR(snapshot_date,'YYYY-MM'), total_square, sold_perc, price_avg FROM domrf_realization WHERE region_code=66 AND endpoint_type='total' AND type_square='total' ORDER BY snapshot_date;"]}
{"type":"entity","name":"Anton_Imported_Apr27_2026","entityType":"event","observations":["Дата: 27.04.2026 поздний вечер. ИМПОРТ SQLite Антона (23.5 MB, 27 таблиц + 8 view) в prod Postgres.","ИСТОЧНИК: C:\\Users\\user\\Downloads\\Telegram Desktop\\db\\db\\domrf.db. Антон параллельно собрал 50+ источников (см. SUMMARY_FULL.md в дампе).","СТРАТЕГИЯ: импорт только уникальных таблиц. Дубли ПРОПУЩЕНЫ: regions, federal_districts, mortgage_rates, escrow_banks, rc_classes/dev_size/city_pop, rc_dynamics_rf, egrn_deals (наш rosreestr_deals 4.97M raw богаче чем его 154K cleaned).","ЗАЛИТЫ 13 НОВЫХ ТАБЛИЦ (197K рядов, +50 MB): domrf_kn_flats (27 563 поквартирный прайс РФ), domrf_kn_objects (1 516 ЖК Свердл с GPS), cbr_mortgage_series (3 308 ЦБ серий), cbr_mortgage_files (19), sber_ddf_metrics (20), yandex_realty_zk (12), yandex_realty_class_prices (3), ekb_districts (9), ekb_metro (10), sv_cities (24), sv_dev_sales (50), domrf_dev_growth (139), rosreestr_rent_deals (1 071). Полный список в Schema_Tables_Map_Apr27.","DEVELOPERS MERGE: было 2 734 в проде → Антон 8 618 (вкл. архивные). Добавлены 5 895 НОВЫХ (2 723 совпали). Итого domrf_developers: 8 629 рядов.","АРТЕФАКТЫ: data/sql/43_anton_import.sql + 44_import_anton_db.py. Список ETL в Schema_ETL_Artefacts_Apr27.","ОГРАНИЧЕНИЕ PRINZIP: в 27 563 flats Антона ОБЩИЙ РФ-срез (10 700 Москва, 286 ЕКБ), PRINZIP-квартиры ОТСУТСТВУЮТ — нужен отдельный probe /api/kn/flats?regions=66&developers=6208_0. TODO в Schema_Open_TODOs_Apr27.","ДОПОЛНИТЕЛЬНЫЕ ИСТОЧНИКИ АНТОНА (НЕ в дампе, требуют отдельного пасса): PRINZIP CRM (49 MB SQLite на analytics.prinzipevent.ru, 102K заявок / 39.9 млрд ₽ revenue), Rosreestr архив 2000-2021 (6.7M сделок, _rosreestr_sv_deals.json 73 MB), 1 267 фото-рендеров ЖК.","PARTNERSHIP НОТЕ: Антон имеет свой граф (114 entities + 339 relations, отдельный jsonl), prod-БД ОБЩИЙ ресурс через SSH-туннель. user подтвердил доступ к CRM/Yandex Realty — 'это и наш доступ тоже'."]}
{"type":"entity","name":"Session_End_Apr27_2026","entityType":"event","observations":["Дата: 27.04.2026 конец дня. СЛЕДУЮЩИЙ ЧАТ НАЧИНАЙ С ЭТОЙ СУЩНОСТИ ПЛЮС 4 ССЫЛОЧНЫх (ниже).","MCP CONNECTOR: crystaldba/postgres-mcp подключён через .mcp.json в project root (в .gitignore). Инструменты: mcp__postgres__execute_sql, list_objects, analyze_db_health, explain_query, get_object_details. Использовать вместо docker run psql.","КЛЮЧЕВОЙ VIEW: v_developer_full_metrics — одним запросом видно portfolio + квартирография доли + realization Свердл sold%/цена. SELECT * FROM v_developer_full_metrics WHERE developer_id IN ('6208_0','5791_0','5832_0').","СДЕЛАНО ЗА ДЕНЬ (ссылки на entity):","1. Lazy-load 5 страниц ДОМ.РФ + stat_series XLSX (DomRF_Lazy_Loaded_Apr27_2026)","2. История 14 мес realization+sold_ready, Янв 2025-Февр 2026 (DomRF_History_Loaded_Apr27_2026)","3. Импорт SQLite Антона 13 таблиц × 197K рядов (Anton_Imported_Apr27_2026)","4. Relations v2: +4 FK связь КВАРТИРЫ↔ЖК↔ДЕВЕЛОПЕРЫ + 4 analytical views (в Schema_Views_Catalogue_Apr27)","5. Два стратегических отчёта: Sverdl_Quartirography_Report_Apr27 + PRINZIP_Strategy_Apr27 + 2 benchmark-карточки (Brusnika, ForumGroup)","• Импорт PRINZIP CRM (49 MB SQLite на analytics.prinzipevent.ru) — 102K заявок / 39.9 млрд ₽ revenue.","• Парсер __NEXT_DATA__ для housing_dev/mortgage_rates SSR-блобов.","• GROUP BY comm_name в v_developer_portfolio — текущий считает корпуса, не жилые комплексы.","GRAPH HEALTH: 127 entities + 388 relations. Размер jsonl ~190K chars. После декомпозиции самый большой entity 8 881 chars (DataSources_Analysis_Apr26). Бывший гигант DB_Schema_Final_Apr26 УДАЛЁН, декомпозирован на 5 Schema_*_Apr27.","HARDLINK TRAP ГРАФА: MCP-сервер atomic-write периодически разрывает hard-link между C:\\mcp\\.aim\\memory-gendesign.jsonl и repo/memory/memory-gendesign.jsonl. Перед git commit ПРОВЕРИТЬ: fc /b memory\\memory-gendesign.jsonl C:\\mcp\\.aim\\memory-gendesign.jsonl. Если разные — del + New-Item -ItemType HardLink.","PROD ДОСТУП: SSH 'gendesign' алиас → 46.173.16.127 с LocalForward 15432:5432. Ключ: C:\\Users\\user\\.ssh\\gendesign_deploy. Пароль PG: 2J2SBPMKuS998fiwhtQqDhMI. Туннель уже открыт (netstat -an | grep 15432 LISTENING).","ОБНОВЛЕНО поздний вечер 27.04.2026: ПРОД-БД теперь 59 таблиц / 1871 MB. +6 таблиц от скрейпера (sale_graph, sales_agg, infrastructure, photos, kn_scrape_runs, kn_scrape_failures).","НОВЫЕ SESSION-ИТОГИ к ранее записанным буллетам: 6) Интерактивный дашборд /analytics (Analytics_Dashboard_Apr27) — 3 страницы на ECharts. 7) Парсер DOM.РФ kn-API + 4 extras (DomRf_Kn_Scraper_Apr27) — собственный sweep Свердл 442+2+1072 = 1516 жК, валидирован через PRINZIP probe (28 жК / 826 квартир / 5409 POI / 5150 фото-мета).","READ FIRST ОБНОВЛЕНО (6 entity вместо 4): Schema_Tables_Map_Apr27 + Schema_Open_TODOs_Apr27 + PRINZIP_Strategy_Apr27 + Sverdl_Quartirography_Report_Apr27 + Analytics_Dashboard_Apr27 + DomRf_Kn_Scraper_Apr27. Первые 4 — данные/стратегия, последние 2 — фичи построенные поверх.","PRIORITY НА СЛЕДУЮЩУЮ СЕССИЮ ОБНОВЛЕН (все из GitHub backlog): 1) #13 Расширить kn-scraper на 442 строящихся Свердл. 2) #14 Импорт PRINZIP CRM. 3) #15 API endpoints /api/v1/analytics/object/{id}/* + UI drill-down. 4) #16 multi-target Dockerfile."]}
{"type":"entity","name":"Analytics_Dashboard_Apr27","entityType":"deliverable","observations":["Дата: 27.04.2026 вечер. ИНТЕРАКТИВНЫЙ ВЕБ-ДАШБОРД АНАЛИТИКИ Свердл рынок + PRINZIP реализован за один проход. План: C:\\\\Users\\\\user\\\\.claude\\\\plans\\\\crispy-waddling-swing.md.","СТЕК: Backend FastAPI (sync SQLAlchemy + psycopg, Pydantic). Frontend Next.js 15 App Router + React 19 + React Query (TanStack) + ECharts (echarts + echarts-for-react v6). 3 страницы, ~16 компонентов, 11 endpoints.","BACKEND ФАЙЛЫ: backend/app/api/v1/analytics.py (роутер 11 endpoints), backend/app/services/analytics_queries.py (SQL-функции). Зарегистрирован в backend/app/main.py prefix /api/v1/analytics tags=['analytics']. Sync Session через get_db().","ENDPOINTS: GET /sverdl/market-pulse · /sverdl/quartirography?source=portfolio|deals · /sverdl/pipeline · /sverdl/districts · /sverdl/yandex-listings · /developers/top?limit · /developers/{id} · /developers/{id}/portfolio · /developers/history?ids=csv · /prinzip/insights (статика из PRINZIP_Strategy_Apr27) · /prinzip/districts (хардкод 8 районов из стратегии).","FRONTEND ФАЙЛЫ: frontend/src/app/analytics/{layout.tsx, page.tsx, prinzip/page.tsx, developers/page.tsx}. Компоненты frontend/src/components/analytics/*: ChartShell, KpiCard, Section, AnalyticsNav, MarketPulseChart, QuartirographyChart, PipelineChart, DistrictTreemap, YandexClassPie, DeveloperLeaderboard (sortable table), VelocityScatter, PrinzipVelocityChart, PrinzipQuartirographyPie, PrinzipGapBar, PrinzipDistrictsBar, InsightCards. lib: analytics-api.ts (React Query hooks), types/analytics.ts.","ROOT ИЗМЕНЕНИЯ: providers.tsx (QueryClientProvider, staleTime 5мин), layout.tsx обёрнут в Providers, page.tsx +ссылка на /analytics. tslib добавлен (требует echarts-for-react). package.json +echarts ^6 +echarts-for-react ^3 +tslib.","STATIC TS BUILD: ✅ npm run type-check clean, npm run build successful 9/9 routes. Размер /analytics 4.52KB, /analytics/prinzip 4.91KB, /analytics/developers 4.26KB First Load 116-120KB.","API SMOKE-TEST через uvicorn + SSH-туннель :15432 — все 11 endpoints отвечают 200, цифры совпадают с Sverdl_Quartirography_Report_Apr27 и PRINZIP_Strategy_Apr27 (sold% PRINZIP 48 / однушки 75.4% / 814 кв.; рынок Свердл Апр 2026 5686 тыс м² 29% 151 397 ₽).","КАК ЗАПУСКАТЬ ЛОКАЛЬНО: backend через docker-compose.yml ИЛИ uv run uvicorn app.main:app + переменная DATABASE_URL='postgresql+psycopg://gendesign:2J2SBPMKuS998fiwhtQqDhMI@127.0.0.1:15432/gendesign'. Frontend cd frontend && npm run dev. Прод: gendsgn.ru через Caddy.","ИЗВЕСТНЫЕ ОГРАНИЧЕНИЯ MVP: (1) /prinzip/districts хардкод из стратегии — нет геометрии районов в ekb_districts для real spatial-join; TODO добавить geometry. (2) Yandex listings в БД всего 12 строк (граф ошибочно говорил 258 — устаревший снимок). (3) v_developer_full_metrics.sverdl_price_avg всегда NULL — KPI ср. цены девелопера пока без данных. (4) Auth нет — публичный URL.","БАГ ИСПРАВЛЕН ВО ВРЕМЯ SMOKE: SQL :region_code в quartirography source=deals использовал не тот биндинг параметра — переименовал на :region_id. Также rosreestr_deals.deal_count это мультипликатор (max 2278) а не штучные сделки — заменено на COUNT(*).","СЛЕДУЮЩИЙ ШАГ: добавить geometry в ekb_districts → real spatial-join PRINZIP-ЖК → carto-карта на /analytics/prinzip. Альтернатива: импорт CRM PRINZIP (49 MB SQLite) → conversion-аналитика. Дальше — авторизация и /analytics/{region}/{developer} параметризация для повторного использования другими клиентами."]}
{"type":"entity","name":"DomRf_Kn_Scraper_Apr27","entityType":"deliverable","observations":["Дата: 27.04.2026. ПАРСЕР НАШ.ДОМ.РФ для КЖ (kn/object) и квартир (слоённый portal/table) реализован. План: C:\\\\Users\\\\user\\\\.claude\\\\plans\\\\crispy-waddling-swing.md.","REAL ENDPOINTS (проверены через chrome-devtools): GET /сервисы/api/kn/object?offset=0&limit=999999&place={place}&objStatus={s}&sortField=default&sortType=desc · GET /portal-kn/api/sales/portal/table?externalId={objId}. Auth header: Authorization: Basic MTpxd2U= (декодируется в 1:qwe — НЕ jwe как было в предыдущей памяти).","PARAMS КЛЮЧЕВЫЕ: place=66 (Регион Свердл) или place='0-4' (город ЕКБ). objStatus: 0=строящиеся, 1=архив-1 (~2 регион), 2=сданные/архив-2 (самый большой бакет). place=66 все 3 статуса = 442+2+1072 = 1516 ЖК (точно совпало с domrf_kn_objects).","СЕРВЕРНЫЙ ФИЛЬТР developers/regions НЕ РАБОТАЕТ — size/page/regions/developers все игнорируются. Поэтому фильтр по девелоперу реализован ЛОКАЛЬНО: фильтруем по developer.companyGroup из ответа. PRINZIP companyGroup=6208.","СТЕК: Playwright Chromium держит живую страницу «новостройки» (cookies+JA3 фингерпринт реального Chrome 147), fetch() из in-page context. httpx вариант НЕ РАБОТАЕТ — ServicePipe WAF проверяет TLS-fingerprint, различает Python httpx от Chrome даже с идентичными cookies. План был 'gibrid Playwright bootstrap + httpx' — НЕ СРАБОТАЛ, пивотнул на 'pure Playwright in-context'.","BACKEND ФАЙЛЫ: backend/app/services/scrapers/{stealth.py, domrf_kn.py, __init__.py}. backend/app/workers/celery_app.py (beat из settings.scrape_kn_cron). backend/app/workers/tasks/scrape_kn.py (с jitter 0..SCRAPE_KN_JITTER_SECONDS). backend/app/api/v1/admin_scrape.py (POST /api/v1/admin/scrape/kn + GET /runs, авторизация через X-Admin-Token = SCRAPE_ADMIN_TOKEN env). data/sql/50_schema_kn_extensions.sql + 50_scrape_kn_flats.py CLI.","FRONTEND: frontend/src/app/admin/scrape/page.tsx — кнопка «Запустить сейчас» (region, devs csv, fetch_flats checkbox) + таблица последних 20 прогонов из kn_scrape_runs (обновляется каждые 5 сек). Token хранится в localStorage.","КОНФИГ: env vars (settings) — SCRAPE_KN_CRON='15 4 * * mon' (любой 5-филд cron), SCRAPE_KN_JITTER_SECONDS=1800 (0..30мин random delay), SCRAPE_KN_DEFAULT_REGIONS='66' (csv), SCRAPE_KN_STATE_PATH='data/playwright_state.json', SCRAPE_ADMIN_TOKEN='' (пусто=выкл admin endpoint).","PLAYWRIGHT FINGERPRINT СНЯТ с локальной машины: data/playwright_state.json (7.3 KB, 26 cookies — AUTH_SESSION_ID, KC_AUTH_SESSION_HASH, ServicePipe NSC_*, Yandex tracking). Закоммичен в git для использования на сервере (worker подхватит при starting cold — ServicePipe видит returning user, не запускает JS-challenge). CLI flags --save-state PATH и --load-state PATH для периодического обновления.","DOCKER: docker-compose.yml +сервисы worker и beat (оба из образа backend). backend/Dockerfile +строка 'playwright install --with-deps chromium' — доп. ~80MB system libs.","СХЕМА-МИГРАЦИЯ ПРИМЕНЕНА: PK сняты с domrf_kn_flats.id и domrf_kn_objects.obj_id, заменены на UNIQUE (id|obj_id, snapshot_date). +индексы (region_cd, snapshot_date). +таблица kn_scrape_runs (журнал прогонов). Backfill region_cd=66 на Антоновых flats: 0 рядов затронуто (их obj_id не матчился с kn_objects).","SMOKE-ТЕСТ PRINZIP ПРОШЁЛ: 4 минуты, run_id=2 в kn_scrape_runs status='done'. Получено: place=66 × (status 0,1,2) = 442+2+1072 = 1516 объектов, локальный фильтр по companyGroup=6208 = 28 PRINZIP ЖК (= jk_count в v_developer_full_metrics!) + 826 квартир (с 814 agg_flats_total разница +12). 31 request total, 22 из них = 404 для сданных (квартиры уже нет в продаже — ок).","TYPE COERCION ИСПРАВЛЕН ДЛЯ BOOLEAN (0/1→bool), DATE ('YYYY-MM-DD'/'DD-MM-YYYY HH:MM:SS'/'IV кв. 2028' → последний день квартала), TEXT (problem_flag из int).","РАСПИСАНИЕ + ПЛАВАЮЩИЙ СТАРТ + КНОПКА выполнены: cron из SCRAPE_KN_CRON env, внутри таска random delay 0..SCRAPE_KN_JITTER_SECONDS берёт время, ручной триггер передаёт skip_jitter=True для немедленного старта.","СЛЕДУЮЩИЙ ШАГ: 1) Развёрнуть worker+beat в docker-compose, проверить celery beat schedule в живюю. 2) Добавить link на /admin/scrape с главной (пока только по прямому URL). 3) Full РФ-sweep (89 регионов) с multi-region cron после стабилизации Свердл. 4) Изучить /сервисы/api/object/{id}/sale_graph + sales_agg для time-series по продажам (видели в нетворке объектной страницы).","EXTRAS-ЭНДПОЙНТЫ ДОБАВЛЕНЫ (per-КЖ, после 27.04.2026 вечер): /сервисы/api/object/{id}/sale_graph?type=apartments|parking (time-series продаж), /sales_agg (текущие агрегаты 3 типа), /infrastructure (POI), /construction/progress/photo (мета+binary).","EXTRAS-ТАБЛИЦЫ: domrf_kn_sale_graph (obj_id, report_month, type, realised, contracted, area_sq, price_avg, snapshot_date), domrf_kn_sales_agg (obj_id, type ∈{apartments,nonliv,parking}, name, total, realised, perc), domrf_kn_infrastructure (нормализованная POI с lat/lon/dist_m/category), domrf_kn_photos (метаданные + local_path к binary). Schema: data/sql/51_schema_kn_extras.sql.","FAILURE LOG: kn_scrape_failures (run_id, obj_id, endpoint, full_url, http_status, error, body_preview, occurred_at). API GET /api/v1/admin/scrape/failures?run_id=N. В admin UI раскрывающийся блок с кнопкой «копировать URL» для ручной проверки в Chrome.","CLI РАСШИРЕН 50_scrape_kn_flats.py: флаги --no-extras / --download-photos / --no-flats / --probe URL. Probe поднимает Playwright-сессию и дёргает один URL — полезно для дебага конкретного фейла.","DOCKER FIX (буг #25): uv.lock не был реген после добавления playwright+tenacity — uv sync --frozen игнорил новые депы. Надо всегда делать 'cd backend && uv lock' после изменения pyproject.toml. Также Dockerfile реструктурирован: Chromium-libs вынесены явно в apt-get install (libnss3, libnspr4, libdbus-1-3, libatk1.0-0, libatk-bridge2.0-0, libcups2, libdrm2, libxkbcommon0, libxcomposite1, libxdamage1, libxfixes3, libxrandr2, libgbm1, libasound2t64, libatspi2.0-0), playwright install chromium без --with-deps, перед rm -rf /var/lib/apt/lists/*. ENV PLAYWRIGHT_BROWSERS_PATH=/opt/playwright для shared chromium-cache.","DOCKER ОПТИМИЗИРОВАН (#16, 27.04 поздний вечер): backend/Dockerfile расщеплён на 2 таргета. target=runner (lean, ~1.6 ГБ) для backend/beat. target=runner-with-chromium (~2.9 ГБ) для worker. docker-compose.{yml,prod.yml} и .github/workflows/deploy.yml пушат 2 GHCR-образа: gendesign-backend + gendesign-worker. Экономия ~1.3 ГБ на backend image.","PER-OBJECT DRILL-IN (#15) ГОТОВ: 5 backend GET endpoints (/object/{id}, /sale_graph, /sales_agg, /infrastructure, /photos) + /prinzip/objects с sparkline-data. UI: новая страница /analytics/objects/[id] (KPI + sale-chart + POI-таблица с фильтром по категории + фото-галерея с lightbox), плюс PrinzipObjectsTable на /analytics/prinzip с sparkline в каждой строке и кнопкой Drill-in.","GitHub issues #13, #14, #15, #16 закрыты 27.04.2026 поздний вечер. README обновлён с разделами 'Запуск 442-sweep' + PRINZIP CRM в карте таблиц + ETL artefacts +52_schema/52_import."]}
{"type":"entity","name":"Prinzip_CRM_Pipeline_Apr27","entityType":"deliverable","observations":["Дата: 27.04.2026 поздний вечер. ПАЙПЛАЙН ДЛЯ ИМПОРТА PRINZIP CRM SQLite (analytics.prinzipevent.ru, 49 МБ, 102K заявок, 9K сделок) реализован, ждёт файла. GitHub #14 закрыт с instructions.","SCHEMA: data/sql/52_schema_prinzip_crm.sql — prinzip_leads (lead_id PK, source/channel, phone_hash SHA256[:16] + phone_last4, email_hash MD5, obj_interest soft FK к domrf_kn_objects, status, converted, deal_id) + prinzip_deals (deal_id PK, lead_id, closed_at, obj_id soft FK, deal_price, payment_type, mortgage_*) + 2 MV (funnel_monthly по месяцам×source, funnel_by_object по КЖ). Применено в прод.","IMPORT SCRIPT: data/sql/52_import_prinzip_crm.py. UPSERT по ID. PII-hashing при импорте (152-ФЗ). Использовать --inspect-only для discovery реальных колонок SQLite и подправить LEAD_FIELD_MAP/DEAL_FIELD_MAP. REFRESH MV автоматически в конце.","BACKEND: 3 endpoints в backend/app/api/v1/analytics.py — /prinzip/funnel/monthly?months=, /prinzip/funnel/by-source?months=, /prinzip/funnel/by-object. Используют MV быстрых выборок.","FRONTEND: 2 новых ECharts-компонента на /analytics/prinzip — PrinzipFunnelSankey (leads→engaged→converted by source, type=sankey) + PrinzipFunnelMonthly (бары leads/engaged/converted + линия conv%). Оба обрабатывают пустой dataset изящно (текст 'Нет данных CRM').","СЛЕДУЮЩИЙ ШАГ: user скачивает SQLite в data/raw/prinzip_crm.sqlite (в .gitignore), запускает импорт. Ожидаемые после импорта: SUM(deal_price)/1e9 ≈ 39.9 (млрд ₽), conversion 2025 ≈ 5.4%, пик 12.81% в 2023. UI будет живым автоматически после импорта."]}
{"type":"entity","name":"Route_Home","entityType":"ui_route","observations":["URL: /","Файл: frontend/src/app/page.tsx","Sitemap-страница с карточками-ссылками на все разделы. 3 секции: Аналитика (4 карточки), Админка (2), Generative (2). Footer со ссылками на /api/v1/docs, /health, GitHub."]}
{"type":"entity","name":"Route_Analytics_Sverdl","entityType":"ui_route","observations":["URL: /analytics","Файл: frontend/src/app/analytics/page.tsx","Свердловский рынок: 4 KPI-карточки + market-pulse line chart + парадокс «строят vs покупают» + pipeline + treemap районов ЕКБ + яндекс listings pie. Публичный доступ."]}
{"type":"entity","name":"Route_Analytics_Prinzip","entityType":"ui_route","observations":["URL: /analytics/prinzip","Файл: frontend/src/app/analytics/prinzip/page.tsx","PRINZIP drill-down: 4 KPI карточки + velocity vs benchmarks (toggle) + квартирография pie + gap-bar к рынку + районы ЕКБ + таблица 28 ЖК с sparkline + insight-карточки. Публичный (CRM-funnel вынесён в /admin/leads)."]}
{"type":"entity","name":"Route_Analytics_Developers","entityType":"ui_route","observations":["URL: /analytics/developers","Файл: frontend/src/app/analytics/developers/page.tsx","Топ-15 девелоперов: sortable leaderboard + velocity scatter + сравнение sold% по месяцам. drill-in через ?id="]}
{"type":"entity","name":"Route_Analytics_Object","entityType":"ui_route","observations":["URL: /analytics/objects/[id]","Файл: frontend/src/app/analytics/objects/[id]/page.tsx","Drill-in одного ЖК: 6 KPI + sale-chart (apartments+parking+price line) + POI-таблица с фильтром по категории/радиусу + фото-галерея с lightbox. Пример: /analytics/objects/60160 (Парк Победы)."]}
{"type":"entity","name":"Route_Admin_Scrape","entityType":"ui_route","observations":["URL: /admin/scrape","Файл: frontend/src/app/admin/scrape/page.tsx + admin/layout.tsx","Token-protected. Ручной запуск скрапера (регион, devs, extras, photos) + живая очередь Celery (active/reserved/scheduled) с кнопками '🛑 Прервать' (SIGTERM) и '⊘ Удалить из очереди' (revoke) + журнал прогонов + журнал ошибок с copy-URL."]}
{"type":"entity","name":"Route_Admin_Leads","entityType":"ui_route","observations":["URL: /admin/leads","Файл: frontend/src/app/admin/leads/page.tsx + admin/layout.tsx","Token-protected. CRM-воронка PRINZIP: Sankey leads→engaged→converted by source + monthly bars + 5 KPI карточек + 4 фильтра (поиск/статус/source/converted) + таблица лидов с пагинацией. PII (phone/email) хешированы, в UI только ***1234."]}
{"type":"entity","name":"Endpoint_Analytics_Object","entityType":"api_endpoint","observations":["GET /api/v1/analytics/object/{obj_id}","GET /api/v1/analytics/object/{obj_id}/sale_graph?type=apartments|parking","GET /api/v1/analytics/object/{obj_id}/sales_agg","GET /api/v1/analytics/object/{obj_id}/infrastructure?category=&max_distance=","GET /api/v1/analytics/object/{obj_id}/photos?limit=","GET /api/v1/analytics/prinzip/objects (с sparkline-data)","Источник: backend/app/api/v1/analytics.py + analytics_queries.py. Публичные."]}
{"type":"entity","name":"Endpoint_Admin_Scrape","entityType":"api_endpoint","observations":["POST /api/v1/admin/scrape/kn (trigger)","GET /api/v1/admin/scrape/runs (journal)","GET /api/v1/admin/scrape/failures?run_id=","GET /api/v1/admin/scrape/queue (Celery inspect: active/reserved/scheduled/workers)","POST /api/v1/admin/scrape/revoke {task_id, terminate}","Auth: X-Admin-Token. Файл: backend/app/api/v1/admin_scrape.py."]}
{"type":"entity","name":"Endpoint_Admin_Leads","entityType":"api_endpoint","observations":["GET /api/v1/admin/leads/ (фильтры: status/source/converted/obj_id/search/date_from/date_to + lim/off)","GET /api/v1/admin/leads/stats?months=12 (KPI)","GET /api/v1/admin/leads/sources (distinct list)","GET /api/v1/admin/leads/funnel/monthly?months=","GET /api/v1/admin/leads/funnel/by-source?months=","GET /api/v1/admin/leads/funnel/by-object","Auth: X-Admin-Token. Файл: backend/app/api/v1/admin_leads.py."]}
{"type":"entity","name":"Module_Scraper_Stealth","entityType":"code_module","observations":["backend/app/services/scrapers/stealth.py","BrowserSession — Playwright Chromium + cookie jar + storage_state load/save. get_json() в браузерном контексте (TLS-fingerprint = real Chrome 147). download_binary() для фото. Auth: Basic MTpxd2U= (1:qwe). Jitter 600-1500мс + concurrency 3."]}
{"type":"entity","name":"Module_Scraper_Kn","entityType":"code_module","observations":["backend/app/services/scrapers/domrf_kn.py","Endpoints для /сервисы/api/kn/object + portal/table + 4 extras (sale_graph/sales_agg/infrastructure/photos). place=66 для Свердл, objStatus 0/1/2 = 442+2+1072. Локальный фильтр по developer.companyGroup. _classify_and_log() — 404 для sale_graph/sales_agg не пишет в failures (ожидаемые для сданных)."]}
{"type":"entity","name":"Module_Celery_App","entityType":"code_module","observations":["backend/app/workers/celery_app.py + workers/tasks/scrape_kn.py","Beat schedule из SCRAPE_KN_CRON env (default '15 4 * * mon'). Random jitter 0-1800с внутри таска. SCRAPE_KN_DEFAULT_REGIONS csv. Ручные триггеры из admin endpoint передают skip_jitter=True."]}
{"type":"entity","name":"Docker_Multi_Target","entityType":"infra","observations":["backend/Dockerfile target=runner (lean, 1.6GB) для backend+beat. target=runner-with-chromium (2.9GB) для worker.","docker-compose.yml выбирает target per service.",".github/workflows/deploy.yml пушит 2 GHCR-образа: gendesign-backend + gendesign-worker.","Экономия 1.3GB на backend image."]}
{"type":"entity","name":"Docker_Auto_Cleanup","entityType":"infra","observations":["deploy.yml после pull вызывает: docker image prune -af --filter 'until=72h' + docker builder prune -af.","Разовая очистка 27.04: 21→13 GB (-8 GB).","Будущие деплои сами чистят image старше 72ч + build cache."]}
{"type":"entity","name":"PII_Compliance_152FZ","entityType":"policy","observations":["PRINZIP CRM импорт (data/sql/52_import_prinzip_crm.py): phone → SHA256[:16] + last 4 digits, email → MD5. raw никогда не попадают в БД. В UI только ***1234. Поддержка 152-ФЗ при будущих запросах удаления."]}
{"type":"entity","name":"Auth_Admin_Token","entityType":"policy","observations":["X-Admin-Token заголовок, значение из SCRAPE_ADMIN_TOKEN env. Пустая строка → admin endpoints отвечают 503 'admin disabled'. Неверный → 401 'invalid admin token'.","Активный токен в prod хранится в backend/.env (gitignored). В UI — localStorage после ввода на /admin/scrape, работает для обеих admin-вкладок."]}
{"type":"entity","name":"Stealth_Fingerprint_State","entityType":"infra","observations":["data/playwright_state.json (в git, 7.3 KB).","26 cookies вкл. AUTH_SESSION_ID, KC_AUTH_SESSION_HASH, ServicePipe NSC_*, Yandex tracking.","Обновляется через 'python data/sql/50_scrape_kn_flats.py --regions 66 --bootstrap-only --save-state data/playwright_state.json'.","Worker подхватывает в cold-start — ServicePipe видит returning user без JS-challenge."]}
{"type":"entity","name":"GitHub_Issue_13_Closed","entityType":"github_issue","observations":["#13 Расширить kn-scraper на 442 строящихся Свердл ЖК","Closed 27.04.2026. Инструкции в README «Запуск 442-sweep». Готов к UI/CLI запуску — кода нового не нужно."]}
{"type":"entity","name":"GitHub_Issue_14_Closed","entityType":"github_issue","observations":["#14 Импорт PRINZIP CRM SQLite","Closed 27.04.2026. Pipeline реализован — schema (52_schema_prinzip_crm.sql) + import script (52_import_prinzip_crm.py) + 6 endpoints + funnel UI в /admin/leads. Ждёт файла от user."]}
{"type":"entity","name":"GitHub_Issue_15_Closed","entityType":"github_issue","observations":["#15 API endpoints /api/v1/analytics/object/{id}/...","Closed 27.04.2026. 5 endpoints + /analytics/objects/[id] page + PrinzipObjectsTable с sparkline."]}
{"type":"entity","name":"GitHub_Issue_16_Closed","entityType":"github_issue","observations":["#16 Multi-target Dockerfile","Closed 27.04.2026. lean backend (1.6GB) + worker-with-chromium (2.9GB)."]}
{"type":"entity","name":"Endpoint_Recommend_Mix","entityType":"api_endpoint","observations":["POST /api/v1/analytics/recommend/mix","Body: {district_name, area_total_m2?, target_class?, months_window=12}","Response: {scope, buckets[5], summary, comparables[≤5]}","Файл: backend/app/api/v1/analytics.py","Pydantic: app/schemas/recommend.py · response_model=RecommendMixOutput"]}
{"type":"entity","name":"Module_Recommend_Query","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: recommend_mix(db, *, district_name, area_total_m2, target_class, months_window, region_code=66)","Возвращает dict (scope/buckets/summary/comparables). Через response_model FastAPI приводит к Pydantic.","Lookup района через ekb_districts ILIKE; исключает 'не определён'.","Класс multiplier через AVG price_from FROM yandex_realty_zk FILTER (WHERE obj_class=:cls).","Comparable ЖК: domrf_kn_objects WHERE addr ILIKE '%район%' AND obj_class match → LEFT JOIN domrf_kn_sales_agg для sold%."]}
{"type":"entity","name":"Schema_Recommend_IO","entityType":"code_module","observations":["backend/app/schemas/recommend.py","RecommendMixInput (district_name str, area_total_m2 float|None ge=100 le=500000, target_class Literal[Comfort/Comfort+/Business/Elite]|None, months_window int 3-36)","RecommendBucket (bucket, share_pct, deal_count, area_avg_m2, area_median_m2, price_p25/median/p75, units_planned, revenue_planned_rub)","RecommendComparable (obj_id, comm_name, dev_name, obj_class, flat_count, sold_perc)","RecommendMixOutput (scope dict, buckets, summary dict, comparables)"]}
{"type":"entity","name":"Module_Bucket_Distribution","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _bucket_distribution(db, region_code, months_window) + _BUCKET_SQL","Вынесено отдельно чтобы переиспользовать при auto-extend до 24 мес.","Возвращает 5 бакетов: deals, area_avg, area_median, price p25/median/p75 (city-wide).","Бакетизация: <30 студия, 30-45 1к, 45-60 2к, 60-80 3к, 80+ 80+ м²."]}
{"type":"entity","name":"Route_Analytics_Recommend","entityType":"ui_route","observations":["URL: /analytics/recommend","Файл: frontend/src/app/analytics/recommend/page.tsx","Публичная (как другие /analytics/*).","Layout: 360px sticky form слева + основной поток справа (KPIs, charts, sliders, table, comparables, caveats).","Все вычисления выручки/weighted-avg клиентские по effectiveShares (после слайдеров)."]}
{"type":"entity","name":"Component_Recommend_Form","entityType":"ui_component","observations":["frontend/src/components/analytics/RecommendForm.tsx","Селект района из useDistricts() с фильтром 'не определён'.","Площадь (опц. 100..500000), класс (опц. Comfort/Comfort+/Business/Elite), окно 12/18/24 мес.","submit triggers useRecommendMix() mutation; кнопка disabled пока пустой район."]}
{"type":"entity","name":"Component_Recommend_Sliders","entityType":"ui_component","observations":["frontend/src/components/analytics/RecommendShareSliders.tsx","5 слайдеров с auto-rescale: при изменении одного, остальные пропорционально пересчитываются к (100-X)%.","Если у других нет массы — распределяет поровну. Round 1 decimal, drift compensation на изменённом слайдере.","Кнопка ↻ Сбросить к рекомендации (disabled когда не было правок). Бейдж '+X.X' рядом со значением показывает delta от API."]}
{"type":"entity","name":"Component_Recommend_Charts","entityType":"ui_component","observations":["Три ECharts-обёртки в frontend/src/components/analytics/:","RecommendBucketsChart.tsx — horizontal bar share% с двумя сериями (серый 'Рекомендация' / синий 'Ваше распределение'), barGap=-100%.","RecommendRevenueChart.tsx — stacked bar (1 категория) с цветовыми сегментами по бакетам, label 'млн ₽' если segment ≥5%.","RecommendBucketsTable.tsx — sortable таблица с p25/median/p75, units_planned, revenue. Алгоритм allocation клиентский.","Chart-серии reactive: пересчитываются при изменении effectiveShares/areaTotal."]}
{"type":"entity","name":"Component_Recommend_Comparables","entityType":"ui_component","observations":["frontend/src/components/analytics/RecommendComparables.tsx","Карточки 3-5 ЖК с comm_name/dev_name/obj_class/flat_count/sold% (цветной бейдж: green ≥50, amber 30-50, red <30).","Каждая карточка — Link на /analytics/objects/{obj_id}.","Grid auto-fill 260px."]}
{"type":"entity","name":"Hook_useRecommendMix","entityType":"code_module","observations":["frontend/src/lib/analytics-api.ts :: useRecommendMix()","useMutation (НЕ useQuery — это POST с body, нет кэширования).","POST /api/v1/analytics/recommend/mix · application/json","TypeScript типы в frontend/src/types/analytics.ts (RecommendMixInput/Output/Bucket/Comparable)."]}
{"type":"entity","name":"Window_Auto_Extend_24mo","entityType":"policy","observations":["Если в любом из 5 бакетов <30 сделок при months_window<24, recommend_mix автоматически расширяет окно до 24 мес для ВСЕХ бакетов (одинаковое окно для согласованности).","Добавляет warning 'Окно расширено до 24 мес' в summary.warnings.","scope.effective_window_months отражает реальное использованное окно (12/18/24)."]}
{"type":"entity","name":"Class_Multiplier_Yandex","entityType":"policy","observations":["Class multiplier = AVG(price_from) FILTER (WHERE obj_class=:cls) / AVG(price_from) overall — из yandex_realty_zk.","Если данных по классу нет → 1.0 + warning. target_class=None → 1.0 без warning.","Применяется к price_p25/median/p75 каждого бакета в ответе."]}
{"type":"entity","name":"Quartirography_Filter_Fix","entityType":"policy","observations":["В _BUCKET_SQL добавлены фильтры выбросов:","realestate_type_code='002001003000' (квартиры; 001=земля, 002=нежилые)","area BETWEEN 10 AND 200 (отсечь коммерческие площади 1974 м² в bucket 80+)","price_per_sqm BETWEEN 30000 AND 1000000","Без них bucket 80+ показывал 719 'сделок' с area_avg=1974 — это были склады/коммерция."]}
{"type":"entity","name":"Limit_District_Median_Null","entityType":"limitation","observations":["Все 8 районов в ekb_districts имеют median_price_per_m2 = NULL (импорт Antona не наполнил).","Текущее поведение recommend_mix: district_factor = 1.0 + warning 'коэффициент района = 1.0'.","Чтобы оживить district_factor — нужен ETL job, наполняющий ekb_districts.median/mean из rosreestr_deals (через парсинг addr → district mapping или geometry)."]}
{"type":"entity","name":"Limit_District_Geometry","entityType":"limitation","observations":["rosreestr_deals имеет только quarter_cad_number, без района. ekb_districts не имеет PostGIS-полигонов.","Поэтому в MVP recommend_mix bucket-распределение город-wide (регион 66). Район влияет ТОЛЬКО на ценовой коэффициент.","v2: добавить PostGIS-полигоны → spatial-join (точка→район) или (cad_quarter→район) → per-district demand."]}
{"type":"entity","name":"Endpoint_Photos_Serve","entityType":"api_endpoint","observations":["GET /api/v1/photos/{obj_id}/{file_id}?size=thumb|full","Файл: backend/app/api/v1/photos.py","size=thumb: WebP 320×240 q=70 из data/raw/domrf_photos/<obj>/<file>_thumb.webp.","Cache-Control: public, max-age=604800, immutable.","size=full: оригинал PNG/JPG из локалки или 302 redirect на DOM.РФ."]}
{"type":"entity","name":"Module_Photo_Thumbs","entityType":"code_module","observations":["backend/app/services/photos/thumbs.py :: make_thumbnail(src, size=(320,240), quality=70)","Pillow + ImageOps.fit (cover) + WebP encode.","thumb_path_for(src) → src.with_name(stem + '_thumb.webp').","Idempotent: skip if dst.exists() and not overwrite. Логирует ошибки и продолжает.","Зависимость: pillow>=10.4.0 в backend/pyproject.toml."]}
{"type":"entity","name":"Photo_Lazy_Fetch","entityType":"policy","observations":["При запросе thumb на фото без локальной копии — endpoint синхронно качает оригинал с DOM.РФ через httpx + Basic auth (1:qwe).","Сохраняет оригинал в data/raw/domrf_photos/<obj>/<file>.{png,jpg}, генерит thumb рядом, UPDATE-ит local_path/thumb_path/downloaded_at, отдаёт thumb.","Подтверждено: urllib + Basic auth работает (200 OK 3.3 МБ PNG) — Playwright-fingerprint не требуется для image CDN, в отличие от JSON API.","Last resort: 302 redirect на upstream если download failed."]}
{"type":"entity","name":"Schema_Photo_Thumb_Path","entityType":"infrastructure","observations":["data/sql/53_schema_kn_thumbs.sql — применена в прод 27.04.2026 поздний вечер.","ALTER TABLE domrf_kn_photos ADD COLUMN IF NOT EXISTS thumb_path TEXT;","CREATE INDEX idx_kn_photos_obj_visible ON domrf_kn_photos (obj_id) WHERE COALESCE(hidden, FALSE) = FALSE;","object_photos analytics-query возвращает thumb_url + full_url (всегда, ссылаются на наш backend)."]}
{"type":"entity","name":"Queue_Optimised_DB","entityType":"policy","observations":["GET /api/v1/admin/scrape/queue: 'active' читается из kn_scrape_runs WHERE status='running' (instant).","inspect.reserved() + inspect.ping() запускаются параллельно в ThreadPoolExecutor с дедлайном 0.8s.","queue_depth — Redis LLEN 'celery'. scheduled — пустой (мы не используем ETA).","Worst-case latency ~600ms vs ~8s раньше (4×inspect timeout=2s)."]}
{"type":"entity","name":"Zombie_Autocleanup","entityType":"policy","observations":["В начале /api/v1/admin/scrape/queue: UPDATE kn_scrape_runs SET status='zombie', finished_at=NOW(), error='auto-marked: no heartbeat 60+ min' WHERE status='running' AND started_at < NOW() - INTERVAL '60 minutes'.","Срабатывает при каждом обращении UI к /queue (poll каждые 3 сек).","Дополнительно: worker_ready hook режет на 5 минут (с heartbeat) — см. Worker_Ready_Hook."]}
{"type":"entity","name":"Redis_Singleton_Lock","entityType":"infrastructure","observations":["backend/app/workers/tasks/scrape_kn.py :: _region_lock(region_code, devs) context manager.","SET NX EX 7200s по ключу 'scrape:kn:lock:<region>:<devs_csv|*>'.","Если beat double-fire или два worker-а — второй сразу выходит {skipped:True, reason:'lock_held'} без INSERT.","TTL 2ч прикроет случай умершего worker (lock сам очистится).","Используется в scrape_kn_region и resume_kn_run одинаково."]}
{"type":"entity","name":"Resume_Checkpoint_Mechanism","entityType":"deliverable","observations":["Дата: 27.04.2026 ночь. Решает Bug_Worker_SIGKILL_Lost_Run.","Phase A в run_region_sweep: после fetch_objects+filter — upsert_objects + _insert_raw + UPDATE kn_scrape_runs SET objects_snapshot=:objs::jsonb, total_obj_count, heartbeat_at=NOW(). Один commit.","Phase B/C (per-object): каждые 10 объектов — _checkpoint(db, run_id, i+1) → UPDATE progress_obj_index, heartbeat_at + commit.","При resume_from_run_id: пропускаем Phase A, читаем objects_snapshot+progress_obj_index+params из старого run, INSERT нового run с resumed_from_run_id, продолжаем с start_index.","UPSERT-семантика всех таблиц защищает от дублей при reprocessing 10-объектового хвоста между checkpoint-ами."]}
{"type":"entity","name":"Schema_Resume_Columns","entityType":"infrastructure","observations":["data/sql/55_schema_scrape_resume.sql — применена в прод 27.04.2026 ночь.","ALTER TABLE kn_scrape_runs ADD: heartbeat_at TIMESTAMPTZ, progress_obj_index INT, total_obj_count INT, objects_snapshot JSONB, params JSONB, resumed_from_run_id BIGINT REFERENCES kn_scrape_runs(run_id).","INDEX idx_kn_scrape_runs_running_heartbeat ON (heartbeat_at) WHERE status IN ('running','resuming').","Размер objects_snapshot для Свердл sweep ~1-2 МБ JSONB на ряд (1516 объектов)."]}
{"type":"entity","name":"Task_Resume_Kn_Run","entityType":"code_module","observations":["backend/app/workers/tasks/scrape_kn.py :: resume_kn_run(run_id) Celery task.","Читает region_codes/developer_ids из исходного run, берёт Redis-lock, вызывает run_region_sweep(resume_from_run_id=N).","Не требует jitter — это срочный resume.","max_retries=2, name='tasks.scrape_kn.resume_kn_run'."]}
{"type":"entity","name":"Worker_Ready_Hook","entityType":"code_module","observations":["backend/app/workers/celery_app.py :: @worker_ready.connect _resume_zombie_runs(sender=None, **_kwargs).","Триггерится после каждого старта Celery worker (включая redeploy).","SELECT runs WHERE status='running' AND objects_snapshot IS NOT NULL AND COALESCE(heartbeat_at, started_at) < NOW() - INTERVAL '5 minutes' LIMIT 20.","UPDATE их в 'zombie' одним апдейтом (audit trail), затем enqueue resume_kn_run.apply_async([rid]) для каждого.","Защищён try/except — провал scan не валит worker."]}
{"type":"entity","name":"Module_Scrape_Log","entityType":"code_module","observations":["backend/app/services/scrapers/domrf_kn.py :: log_progress(db, run_id, message, *, level='info', stage=None, obj_id=None).","INSERT INTO kn_scrape_log (run_id, level, stage, obj_id, message). message[:500] чтобы не раздуть.","Best-effort: SQL ошибки swallowed → не валят sweep.","Расставлен в run_region_sweep на: start, fetch_objects (per status), filter_devs, phase_a, fetch_flats (каждые 25), extras (каждые 10), resume, done, failed."]}
{"type":"entity","name":"Schema_Scrape_Log_Table","entityType":"infrastructure","observations":["data/sql/54_schema_scrape_log.sql — применена в прод 27.04.2026 ночь.","kn_scrape_log (log_id BIGSERIAL PK, run_id BIGINT REFS kn_scrape_runs ON DELETE CASCADE, ts TIMESTAMPTZ DEFAULT NOW(), level TEXT CHECK in ('info','warn','error'), stage TEXT, obj_id INT, message TEXT NOT NULL).","Индексы: (run_id, ts DESC), (ts DESC). ON DELETE CASCADE — лог чистится с run."]}
{"type":"entity","name":"Endpoint_Scrape_Logs","entityType":"api_endpoint","observations":["GET /api/v1/admin/scrape/logs?run_id=&since_id=&limit=200 (max 1000).","Файл: backend/app/api/v1/admin_scrape.py.","Auth: X-Admin-Token. since_id — для инкрементального polling (передавай max log_id виденного).","Возвращает rows ORDER BY log_id DESC."]}
{"type":"entity","name":"UI_Scrape_Progress_Panel","entityType":"ui_component","observations":["Секция в frontend/src/app/admin/scrape/page.tsx :: 'Прогресс задач'.","Тёмная консоль (background #0f172a, моноширинный) с цветовой раскладкой INFO/WARN/ERROR.","Формат строки: 'HH:MM:SS LEVEL [run-N · stage · obj=X] message'.","useQuery(refetchInterval: 3000) с фильтром по run_id (input).","scroll-контейнер 360px maxHeight."]}
{"type":"entity","name":"Bug_Worker_SIGKILL_Lost_Run_Fixed","entityType":"bug","observations":["Симптом: при redeploy/SIGKILL/OOM worker умирал без вызова except/finally → row в kn_scrape_runs оставался status='running' навечно, вся работа sweep терялась.","Closed 27.04.2026 ночь. Resolved by Resume_Checkpoint_Mechanism + Worker_Ready_Hook + Schema_Resume_Columns.","User-reported: 'после авто деплоя умираю и остаются не завершенные зомби'."]}
{"type":"entity","name":"Bug_Beat_Double_Fire_Fixed","entityType":"bug","observations":["Симптом: 27.04 у user'а run_id=4 и run_id=5 стартовали в одну секунду (16:38:01) — beat double-fire или два beat-контейнера.","UI показывал два 'в работе' дубликата одного и того же региона.","Closed 27.04.2026 ночь. Resolved by Redis_Singleton_Lock в scrape_kn_region (SET NX EX). Второй выходит с skipped:True/lock_held без INSERT."]}
{"type":"entity","name":"Bug_Inspect_Slow_Queue_Fixed","entityType":"bug","observations":["Симптом: GET /admin/scrape/queue ждал до 8s (4 вызова inspect.* с timeout=2s последовательно).","User-reported: 'очередь так же долго получается'.","Closed 27.04.2026 ночь. Resolved by Queue_Optimised_DB (active из БД, inspect в ThreadPoolExecutor с дедлайном 0.8s)."]}
{"type":"entity","name":"Bug_RealEstate_Outliers_Fixed","entityType":"bug","observations":["Симптом: bucket 80+ в recommend_mix выдавал 719 'сделок' с area_avg=1974 м² и medianna 155K ₽/м² — это нежилые помещения / склады.","rosreestr_deals.realestate_type_code: 002001003000=квартиры, 002001001000=земля, 002001002000=нежилые.","Closed 27.04.2026 ночь. Resolved by Quartirography_Filter_Fix в _BUCKET_SQL."]}
{"type":"entity","name":"Photo_Storage_Pipeline","entityType":"deliverable","observations":["Дата: 27.04.2026 поздний вечер. Кеширование thumb-копий фото DOM.РФ на backend.","Архитектура: scraper скачивает оригинал PNG/JPG → Pillow генерит 320×240 WebP q=70 рядом → path в thumb_path колонке.","Endpoint /api/v1/photos/{obj}/{file}?size=thumb|full отдаёт из локалки (FileResponse, Cache-Control 7d).","Lazy fetch при первом запросе thumb на фото без локальной копии (httpx + Basic auth).","Frontend перешёл с Next/Image на прямой <img src={thumb_url}> — backend выдаёт уже оптимизированный WebP, никаких cold-hit оптимизатора в dev.","lightbox использует full_url — выдаёт оригинал или redirect на DOM.РФ."]}
{"type":"entity","name":"Recommend_Level1_Apr27","entityType":"deliverable","observations":["Дата: 27.04.2026 ночь. Реализован Уровень 1 rule-based рекомендатора квартирографии. База для ML v2.","Алгоритм: city-wide ДДУ-сделки Свердл (rosreestr_deals) бакетизируются по площади (5 бакетов) × дистрикт multiplier (median_price ratio) × класс multiplier (yandex_realty_zk).","Allocation: если задан area_total_m2 — units_planned = round(allocated/area_avg), revenue = units × area_avg × price_median.","User-confirmed дизайн-решения: input=district_name, class через yandex_realty_zk, output=4 секции, slider auto-rescale, fallback 24мес при <30 сделок.","Реальные цифры для Свердл 12 мес (после фильтров): студии 72 сделок/119K₽, 1к 27/105K, 2к 12/105K, 3к 10/154K, 80+ 73/164K."]}
{"type":"entity","name":"Session_Resume_Recommend_Apr28_2026","entityType":"event","observations":["Дата: переход 27→28.04.2026 ночь. Продолжение Session_End_Apr27_2026.","СДЕЛАНО ЗА СЕССИЮ (ссылки на entity):","1. Photo_Storage_Pipeline (Pillow тхумбы + endpoint /api/v1/photos + lazy fetch + frontend переход с Next/Image).","2. Queue_Optimised_DB + Zombie_Autocleanup + Redis_Singleton_Lock (исправили 8s→0.6s латенси и beat double-fire).","3. Module_Scrape_Log + Schema_Scrape_Log_Table + Endpoint_Scrape_Logs + UI_Scrape_Progress_Panel (живой лог прогресса в админке).","4. Resume_Checkpoint_Mechanism + Schema_Resume_Columns + Task_Resume_Kn_Run + Worker_Ready_Hook (resume после redeploy с checkpoint каждые 10 объектов).","5. Recommend_Level1_Apr27 + Endpoint_Recommend_Mix + Module_Recommend_Query + Schema_Recommend_IO + Module_Bucket_Distribution + Route_Analytics_Recommend + 5 UI-компонентов + useRecommendMix.","BUGS CLOSED: Bug_Worker_SIGKILL_Lost_Run_Fixed, Bug_Beat_Double_Fire_Fixed, Bug_Inspect_Slow_Queue_Fixed, Bug_RealEstate_Outliers_Fixed.","OPEN TODOs (новые): Limit_District_Median_Null — нужен ETL для наполнения ekb_districts.median_price; Limit_District_Geometry — PostGIS-полигоны районов для per-district demand.","ПРОД SCHEMA: 4 новые миграции применены: 53_kn_thumbs.sql, 54_scrape_log.sql, 55_scrape_resume.sql, плюс изменения в domrf_kn_photos (thumb_path) и kn_scrape_runs (heartbeat_at, progress_obj_index, total_obj_count, objects_snapshot, params, resumed_from_run_id).","ПРИОРИТЕТЫ НА СЛЕДУЮЩУЮ СЕССИЮ: 1) ETL ekb_districts.median из rosreestr_deals (оживит district_factor в recommend_mix). 2) PostGIS-полигоны РАЙОНОВ ЕКБ для spatial-join. 3) PRINZIP CRM импорт (ожидает SQLite). 4) Тест resume в проде (запустить sweep × restart worker × проверить '♫ Resume from index N')."]}
{"type":"entity","name":"Bug_SQLAlchemy_DoubleColon_Cast","entityType":"bug","observations":["Системный баг: SQLAlchemy 2.0 + psycopg3 ИГНОРИРУЕТ привязку в конструкции :name::type. Парсер named-bind видит :name, но ::type не распознаётся как PostgreSQL cast → остаётся литералом в скомпилированном SQL.","Симптом: psycopg.errors.SyntaxError: syntax error at or near ':' на INSERT/UPDATE.","Решение (canonical): всегда использовать CAST(:name AS type) вместо :name::type.","Найден в 5 местах (28.04.2026): исправлены. analytics_queries.py:1222 (recommend_mix comparables :cls::text) · domrf_kn.py:1024 (resume INSERT :rc/devs/params/objs::*) · domrf_kn.py:1060 (new run INSERT :params::jsonb) · domrf_kn.py:1144 (Phase A snapshot UPDATE :objs::jsonb) · admin_leads.py:70 (lead filter :date_to::date).","Эффект бага: 100% блокировка run_region_sweep на INSERT, worker принимал task'и но никогда не создавал run_id."]}
{"type":"entity","name":"Pattern_CAST_AS_Type","entityType":"policy","observations":["Использовать CAST(:name AS type) в любых SQL-выражениях SQLAlchemy text() вместо :name::type.","Обратный паттерн ARRAY[:rc]::int[] РАБОТАЕТ — :: приклеено к закрывающей скобке, а не к bind-name.","Правило проверки перед PR: grep -nE ':[a-z_]+::[a-z]' backend/app — должен выводить пустоту.","Это попадало в 4 разных PR'а (recommend_mix, run_region_sweep refactor, admin_leads filter) — выработать lint-правило с ruff или pre-commit на будущее."]}
{"type":"entity","name":"Recommend_Velocity_Calculator_Apr28","entityType":"deliverable","observations":["Дата: 28.04.2026. Расширение Recommend_Level1_Apr27 — live-калькулятор 'цена ↔ темп ↔ срок ↔ ликвидность'.","По запросу Антона для CEO: 'Изменил цену → изменилась скорость продаж. Изменил срок → система показала какая цена/ассортимент нужны. Изменил ассортимент → изменилась ликвидность, средний чек, темп.'","Архитектура: API выдаёт BASELINE (velocity_baseline + elasticity коэффициент). Все слайдеры и target_months рассчитываются КЛИЕНТСКИ — без round-trip.","Новые компоненты: Component_Recommend_Velocity_Panel + Component_Recommend_Liquidity_Chart. Расширены: BucketsTable (+колонки Темп/Срок), RecommendForm (+target_months input).","Headline для CEO: 'Цена × выручка · срок · чек · темп · ликвидность' одной тёмной плашкой."]}
{"type":"entity","name":"Module_Velocity_Baseline","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _velocity_baseline(db, *, region_code, district_name, target_class)","SQL: median+avg из domrf_kn_sale_graph WHERE type='apartments' за 24 мес для ЖК в (район+класс) через obj_pool с addr ILIKE район.","Результат: {realised_per_month_avg, realised_per_month_median, objects_count, observations}.","Если sale_graph пуст — fallback на rosreestr deals/month (city-wide). Сейчас sale_graph покрывает 2 ЖК, поэтому в 99% случаев идёт fallback."]}
{"type":"entity","name":"Module_Elasticity_Coef","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _elasticity_coef(db, *, region_code, district_name, target_class)","SQL: regr_slope(LN(realised), LN(price_avg)) + regr_r2 на sale_graph за 36 мес для (район+класс).","Выдаёт {elasticity, r2, n, source: 'regression'|'fallback'}. fallback = -1.5 при n<30 или r2<0.1 или slope>=0.","Используется во фронте для расчёта velocity = base × price_factor^elasticity."]}
{"type":"entity","name":"Module_Required_Price_Factor","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: внутри recommend_mix (пункт 5c).","Inverse mode: если target_months задан, система решает required_price_factor = (total_units / target_months / base_total_velocity)^(1/elasticity).","Если < 0.7 → warning 'скидка >30% нереалистична, рассмотри сдвиг ассортимента'.","В UI: 'Применить →' кнопка копирует значение в price_factor слайдер (обрезая в [0.85, 1.15])."]}
{"type":"entity","name":"Module_Liquidity_Score_24mo","entityType":"code_module","observations":["Клиентский расчёт в RecommendVelocityPanel.tsx + backend дублирует в recommend_mix пункте 5d.","Формула: liquidity = Σ (min(1, 24/months_to_sellout) × units_planned) / total_units × 100. Диапазон 0..100.","Цветовые пороги: ≥0a7a3a (зелёный) >=70, #9a6700 (жёлтый) 40⋅0, #b3261e (красный) <40."]}
{"type":"entity","name":"Component_Recommend_Velocity_Panel","entityType":"ui_component","observations":["frontend/src/components/analytics/RecommendVelocityPanel.tsx","4 больших KPI: Средний чек / Срок реализации / Темп продаж / Ликвидность (светофор).","Slider price_factor 0.85..1.15 step=0.01 — live recompute всех KPI по формуле base × pf^elasticity.","Inverse-mode плашка когда target_months задан: показывает required_price_factor + кнопка 'Применить'.","Нижняя подпись 'Эластичность -1.5 (регрессия sale_graph: R²=X, n=N или fallback)' — для CEO-легитимности."]}
{"type":"entity","name":"Component_Recommend_Liquidity_Chart","entityType":"ui_component","observations":["frontend/src/components/analytics/RecommendLiquidityChart.tsx","ECharts line+area: кумулятивные % продаж по месяцам 0..36, пунктир-markline на 24 мес.","При изменении priceFactor или mix-слайдеров кривая live пересчитывается.","Empty-state: 'Укажи площадь — посчитаем сколько и когда продастся'."]}
{"type":"entity","name":"Feature_Headline_CEO","entityType":"ui_component","observations":["Тёмная плашка сразу под H1 на /analytics/recommend.","Формат: '💼 «Район · Класс · X м²»: выручка млн ₽ · за ~Y мес · ср. чек Z М ₽ · темп W кв/мес · ликвидность V/100'.","Генеритсь backend'ом в recommend_mix.summary.headline — для screenshots/экспорта. Фронт обёртывает в div с emoji + bold район/класс/площадь.","Известная проблема: int(months) округляет 0.66 → 0 мес. TODO — использовать f'{x:.1f}'."]}
{"type":"entity","name":"Bug_Velocity_Mix_Static_OPEN","entityType":"bug","observations":["Симптом: при движении mix-слайдеров KPI Срок/Темп практически не меняются. Из скрина 28.04: 'Темп 159.0 кв/мес' статичен, 'Срок 0.8 мес' округляется в 0 мес в headline.","Причина: все 5 бакетов используют ОДИН market_velocity_per_month. Групповая формула baseVelocity = Σ(per_bucket_v × effective_share/share) ≡ city_total независимо от mix.","Установлен и отложен (Tier α work).","Решение: per-bucket velocity = bucket_market_share_in_total × city_v / N_competitors. Из rosreestr по бакетам отдельно (студии 710/24=30, 1к 1306/24=54, ит.д.) и поделить на N_active_ЖК в районе/классе."]}
{"type":"entity","name":"Bug_Velocity_Unrealistic_OPEN","entityType":"bug","observations":["Симптом: 'Срок реализации 0.8 мес' / 'Темп 159 кв/мес' / 'Ликвидность 100/100' — фантастичные числа.","Причина: при fallback (sale_graph пуст) market_velocity_per_month = total_deals / months_window. Для Свердл 3815 сделок / 24 = 159 кв/мес — темп РЫНКА, не проекта. 107 юнитов ÷ 159 = 0.7 мес — 'все сделки рынка идут у нас'.","Решение (Tier α): velocity_per_project = market_velocity / N_active_competing_ЖК (из domrf_kn_objects с site_status='Строящиеся' в (район+класс)). Для Свердл ~442 active → 0.36 кв/мес на ЖК → срок 100-300 мес.","Плюс prominent warning-badge в UI 'Темп грубый, нужен sale_graph для точных данных'."]}
{"type":"entity","name":"Bug_Recommend_500_CAST_Fixed","entityType":"bug","observations":["Симптом: POST /api/v1/analytics/recommend/mix возвращал 500 с 'syntax error at or near :' на строке :cls::text IS NULL.","Причина: SQLAlchemy не парсит :name::type (см. Bug_SQLAlchemy_DoubleColon_Cast).","Closed 28.04.2026. Resolved by Pattern_CAST_AS_Type в analytics_queries.py:1222 (CAST(:cls AS TEXT) IS NULL)."]}
{"type":"entity","name":"Bug_Phase_A_INSERT_500_Fixed","entityType":"bug","observations":["Симптом (28.04.2026 23:29): в /admin/scrape 'Кнопка не работает' — worker принимал task'и (task_received в kn_scrape_log), но НИКОГДА не создавал run_id в kn_scrape_runs.","Диагностика: docker compose logs worker показал трейсбек 'syntax error at or near : LINE 8: :params::jsonb' на INSERT INTO kn_scrape_runs.","Причина: в 4 местах (resume INSERT, new run INSERT, snapshot UPDATE) были :name::jsonb / :name::int[] / :name::text[] — SQLAlchemy bug.","Closed 29.04.2026. Resolved by Pattern_CAST_AS_Type в domrf_kn.py:1024,1060,1144 и бонусом admin_leads.py:70 (:date_to::date).","Smoke: выполнил INSERT руками через SSH-тоннель — run_id=8 создан (и удалён вручную), SQL парсится ОК."]}
{"type":"entity","name":"Bug_Lock_Held_Silent_Fixed","entityType":"bug","observations":["Симптом: при повторном нажатии кнопки task_id возвращаетсь, но run_id не появляется. Никаких логов.","Причина: Redis-lock от зомби-воркера с TTL=2ч блокирует новые task'и · воркер своим retry получает lock_held и выходит без записи в БД.","Closed 28.04.2026 by: TTL_Lock_Reduction (7200→1800), Module_Lock_Diagnostic_Logs (task_received/skipped в kn_scrape_log), Endpoint_Release_Lock + Param_Force_Trigger + UI '🔓 Снять Redis-lock' кнопка."]}
{"type":"entity","name":"Endpoint_Release_Lock","entityType":"api_endpoint","observations":["POST /api/v1/admin/scrape/release-lock","Body: {region_code, developers}. Auth: X-Admin-Token.","Файл: backend/app/api/v1/admin_scrape.py.","Вручную удаляет Redis ключ 'scrape:kn:lock:<region>:<devs>'. Нужен для emergency-режима (зомби-воркер оставил lock).","Возвращает {released: bool, region_code, developers}."]}
{"type":"entity","name":"Param_Force_Trigger","entityType":"policy","observations":["Новый параметр в TriggerKnRequest: force: bool = False.","При force=True эндпоинт /admin/scrape/kn вызывает force_release_lock() ПЕРЕД apply_async — снимает зомби-lock.","Фронтенд: чекбокс '⚡ Force (снять lock)' в форме запуска (красный при включении).","Ответ содержит lock_was_released: bool — видно был ли lock."]}
{"type":"entity","name":"Module_Lock_Diagnostic_Logs","entityType":"code_module","observations":["backend/app/workers/tasks/scrape_kn.py :: _log_task_received(region, devs, task_id) и _log_task_skipped(region, devs, task_id, reason).","Пишут в kn_scrape_log с run_id=NULL (run_id не существует до Phase A INSERT). FK accept NULL.","task_received вызывается в первой строке scrape_kn_region и resume_kn_run.","task_skipped вызывается при lock_held.","Даёт UI понимание 'worker подхватил и что сделал' даже когда run_region_sweep не запускается."]}
{"type":"entity","name":"TTL_Lock_Reduction","entityType":"infrastructure","observations":["_LOCK_TTL_SECONDS в backend/app/workers/tasks/scrape_kn.py: 7200 (2ч) → 1800 (30мин).","Обоснование: full Свердл sweep идёт ~25-30 мин — 30 мин это потолок. Зомби-lock истекает за полчаса, не блокирует новые task'и в рабочий день.","Heartbeat-based autoclean в /queue endpoint по всё равно подхватит зомби-runs за 10 мин по heartbeat_at."]}
{"type":"entity","name":"Phase_A_Heartbeat_Tick","entityType":"code_module","observations":["Добавлено _checkpoint(db, run_id, 0) в run_region_sweep ПОСЛЕ каждого фетча objStatus (Phase A).","Phase A для 1516 ЖК идёт ~3 мин. Без heartbeat-tick новый 10-мин autoclean threshold мог бы ложно пометить легитимный sweep как zombie.","progress_obj_index ставится 0 (снапшот ещё не сохранён), но heartbeat_at = NOW() обновляется в каждой итерации фетча."]}
{"type":"entity","name":"Autoclean_Heartbeat_Threshold","entityType":"policy","observations":["Изменён фильтр zombie autoclean в /api/v1/admin/scrape/queue.","Было: status='running' AND started_at < NOW() - 60 minutes (резал валидные долгие sweep'ы).","Стало: status='running' AND COALESCE(heartbeat_at, started_at) < NOW() - 10 minutes (heartbeat обновляется каждые ~30 сек, 10 мин без него = точно мёртв).","COALESCE подхватывает legacy-runs без heartbeat по старому критерию."]}
{"type":"entity","name":"Deploy_Cache_State_Apr28","entityType":"infrastructure","observations":["Проверка 28.04.2026: GHA cache (cache-from/cache-to type=gha,scope=*) УЖЕ в .github/workflows/deploy.yml для всех 3 билдов (backend/worker/frontend). Не нужно добавлять.","Сделаны дополнительные исправления для фактического хита кэша:","1. .gitignore +*.tsbuildinfo (frontend/tsconfig.tsbuildinfo был tracked и менялся в каждом коммите → invalidate frontend context).","2. git rm --cached frontend/tsconfig.tsbuildinfo.","3. frontend/.dockerignore расширен: +.git +*.tsbuildinfo +.next/cache +tests +*.md +coverage.","4. backend/.dockerignore расширен: +.git +data/raw +data/raw_endpoints +*.log +*.md +.coverage.","5. backend/Dockerfile +RUN --mount=type=cache,target=/root/.cache/uv на uv sync. +RUN --mount=type=cache,target=/var/cache/apt на apt install (во всех 3 стейджах).","6. frontend/Dockerfile +RUN --mount=type=cache,target=/root/.npm на npm ci.","Ожидаемый эффект: 8 мин → 2-3 мин на типовых Python-правках."]}
{"type":"entity","name":"Tier_Alpha_Velocity_Overhaul_TODO","entityType":"feedback","observations":["Отложенная работа (Tier α, введён в плане 28.04.2026): переделка velocity-модели recommend_mix.","Части:","A. _active_competitors_count(db, district, class) — SELECT COUNT FROM domrf_kn_objects WHERE site_status='Строящиеся' AND addr ILIKE district AND obj_class=cls.","B. Per-bucket velocity = bucket_market_share × city_total_velocity / N_competitors. Отдельный темп для каждого bucket'а.","C. headline format: f'{months:.1f} мес' вместо int().","D. Warning-badge в RecommendVelocityPanel когда velocity_source==fallback.","E. Headline compact: 3 главных метрики вместо 5.","Делается ПОСЛЕ стабилизации скрапера (Bug_Phase_A_INSERT_500_Fixed)."]}
{"type":"entity","name":"Session_Apr28_Calc_Scraper_Apr28_2026","entityType":"event","observations":["Дата: 28.04.2026 вечер → ночь. Продолжение Session_Resume_Recommend_Apr28_2026.","СДЕЛАНО:","1. Recommend_Velocity_Calculator_Apr28 (live калькулятор цена↔темп↔срок↔ликвидность) + Module_Velocity_Baseline + Module_Elasticity_Coef + Module_Required_Price_Factor + Module_Liquidity_Score_24mo + Component_Recommend_Velocity_Panel + Component_Recommend_Liquidity_Chart + Feature_Headline_CEO.","2. Bug_Recommend_500_CAST_Fixed (CAST(:cls AS TEXT) вместо :cls::text).","3. Deploy_Cache_State_Apr28 (.gitignore tsbuildinfo, .dockerignore tighten, uv/npm/apt cache mounts).","4. Module_Lock_Diagnostic_Logs (task_received/skipped в kn_scrape_log) + Endpoint_Release_Lock + Param_Force_Trigger + TTL_Lock_Reduction (7200→1800) + Autoclean_Heartbeat_Threshold (60→10 мин) + Phase_A_Heartbeat_Tick.","5. Bug_Phase_A_INSERT_500_Fixed (4 места :name::type → CAST). Главный corner-case сессии — объясняет почему скрапер не работал 26+ часов.","6. Bug_Lock_Held_Silent_Fixed.","OPEN BUGS ПОСЛЕ СЕССИИ: Bug_Velocity_Mix_Static_OPEN, Bug_Velocity_Unrealistic_OPEN. Оба решает Tier_Alpha_Velocity_Overhaul_TODO.","ПРИОРИТЕТЫ НА СЛЕДУЮЩУЮ: 1) Развернуть Bug_Phase_A_INSERT_500_Fixed в прод, проверить что sweep реально проходит 1516 ЖК + 28K flats. 2) Tier_Alpha (Bug_Velocity_Mix_Static + Bug_Velocity_Unrealistic). 3) ЭТИЛЬАРНЫе тиры 1-3 предикта (mortgage rate impact, region trend multiplier, pipeline pressure, hedonic features, developer reputation)."]}
{"type":"entity","name":"Geo_District_Mapping_Apr29","entityType":"deliverable","observations":["Дата: 29.04.2026. Главная победа сессии — ЛОКАЛЬНОЕ решение Limit_District_Geometry: железная привязка ЖК ЕКБ к 8 районам через PostGIS-полигоны OSM.","Архитектура: Overpass API (admin_level=9 в bbox ЕКБ) → shapely сборка OSM way-members в MultiPolygon → ekb_districts_geom с GIST-индексом → ST_Contains UPDATE domrf_kn_objects.district_name.","Результат backfill: Академический 586/208 строящихся, Чкаловский 510/158, Верх-Исетский 288/80, Ленинский 284/98, Орджоникидзевский 266/58, Кировский 236/68, Октябрьский 204/50, Железнодорожный 204/39. NULL=454 ЖК вне ЕКБ (Первоуральск, Н.Тагил).","Эффект в recommend_mix: velocity_source переключился с 'rosreestr_fallback' на 'sale_graph' (Академический: 104 ЖК × 1872 точки), competitors_count 208 вместо fallback singleton, comparable ЖК реальные (ТЭН СТАРТ, Эхо леса, KORTROS Eleven)."]}
{"type":"entity","name":"Module_Fetch_Ekb_Districts","entityType":"code_module","observations":["data/sql/56_fetch_ekb_districts.py — CLI загрузчик Overpass API → PostGIS.","Overpass query: relation['boundary'='administrative']['admin_level'='9']['name'~'район'] в bbox ЕКБ (56.71..57.00 шир. / 60.42..60.95 долг.). Возвращает 8 relations.","shapely-ассемблинг: way-members рваные в OSM, polygonize() сшивает их в closed rings, .buffer(0) исправляет self-intersections.","Кэш в data/raw/ekb_districts.geojson (коммитится в git — повторно Overpass не дыбаем).","Flags: --force-refetch (игнор кэш), --dry-run (без БД).","OSM names → ekb_districts.district_name хардкод-мап из 8 районов ('Академический район' → 'Академический')."]}
{"type":"entity","name":"Schema_Ekb_Districts_Geom","entityType":"infrastructure","observations":["data/sql/56_schema_ekb_districts_geom.sql — применена в прод 29.04.2026.","CREATE TABLE ekb_districts_geom (district_name TEXT PK FK→ekb_districts, geom geometry(MultiPolygon, 4326), osm_id BIGINT, fetched_at TIMESTAMPTZ).","GIST index idx_ekb_districts_geom_geom для spatial-join performance.","8 районов залиты из OSM (osm_id 5803327..14040275). Площади ST_Area в диапазоне 5-50 км²."]}
{"type":"entity","name":"Schema_Kn_Objects_District_Column","entityType":"infrastructure","observations":["data/sql/57_kn_objects_district.sql — применена в прод 29.04.2026.","ALTER TABLE domrf_kn_objects ADD COLUMN district_name TEXT.","INDEX idx_kn_objects_district WHERE district_name IS NOT NULL.","Initial backfill UPDATE через ST_Contains(d.geom, ST_MakePoint(o.lon, o.lat)) для region_cd=66.","3032 ЖК Свердл: 2578 привязаны к 8 районам, 454 NULL (вне ЕКБ)."]}
{"type":"entity","name":"File_Ekb_Districts_Geojson_Cache","entityType":"infrastructure","observations":["data/raw/ekb_districts.geojson — коммитится в git.","FeatureCollection с 8 MultiPolygon-фичами. Properties: name (OSM), osm_id, admin_level=9.","Источник: Overpass API в 29.04.2026 в 7:57 утра. При обновлении OSM-бордеров перефетчить через --force-refetch."]}
{"type":"entity","name":"Module_Backfill_District_Names_Scraper","entityType":"code_module","observations":["backend/app/services/scrapers/domrf_kn.py :: _backfill_district_names(db, snapshot_date, region_code).","Вызывается в run_region_sweep ПОСЛЕ Phase A commit (когда свежие upsert_objects уже в БД).","UPDATE через ST_Contains только для region_cd=66 (другие регионы полигонов не имеют сейчас).","Best-effort: try/except, не валит sweep при сбое привязки."]}
{"type":"entity","name":"Pattern_OSM_Overpass_Admin_Level","entityType":"policy","observations":["Для России в OSM городские районы = admin_level=9. Город как целое = 8.","Прямой query: relation['boundary'='administrative']['admin_level'='9'](bbox) работает лучше чем area-based поиск (last раз area['name'='Екатеринбург'] → 0 элементов).","User-Agent header обязателен — Overpass банит default urllib UA."]}
{"type":"entity","name":"Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed","entityType":"bug","observations":["Симптом: несмотря на успешный ночной sweep (1516 объектов + 192K квартир + 7938 sale_graph rows), recommend_mix пишет 'недостаточно данных'.","Причина: фильтр addr ILIKE '%Академический%' даёт 0 объектов — все domrf_kn_objects.addr = 'Город Екатеринбург', без названия района.","Closed 29.04.2026 by Geo_District_Mapping_Apr29: в 4 местах в analytics_queries.py заменили 'addr ILIKE :dn' на 'district_name = :dn' (_velocity_baseline, _elasticity_coef, _active_competitors_count, comparable query)."]}
{"type":"entity","name":"Module_Graceful_Obj_Class_Degrade","entityType":"code_module","observations":["В recommend_mix: target_class_for_geo — если в районе нет ни одного ЖК с НЕ-NULL obj_class — фильтр по классу ОПУСКАЕТСЯ на уровне velocity/elasticity/comparable запросов.","class_multiplier (из yandex_realty_zk) на ценах продолжает работать.","Причина: kn-API возвращает obj_class=NULL для ВСЕХ 3032 ЖК Свердл (отдельный баг скрейпера). Без degrade фильтр obj_class='Comfort' режет всё в НОЛЬ.","Warning пользователю: 'obj_class не заполнен — фильтр по классу игнорируется'."]}
{"type":"entity","name":"Bug_Kn_API_Obj_Class_Always_Null_OPEN","entityType":"bug","observations":["Симптом: domrf_kn_objects.obj_class=NULL для ВСЕХ 3032 ЖК Свердл. SELECT obj_class, COUNT(*) GROUP BY obj_class даёт только (NULL, 3032).","Причина: kn-API возвращает фильтр по objClass но сам objClass в ответе пустой, или _norm_object не читает правильный ключ.","Временный обход: Module_Graceful_Obj_Class_Degrade игнорирует target_class в geo-запросах.","Реальный фикс: проверить реальные ключи kn-API response через chrome-devtools пробив, поправить _norm_object."]}
{"type":"entity","name":"Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN","entityType":"bug","observations":["Симптом: domrf_kn_flats.price_per_m2 заполнен только для 288 из 192K квартир (0.15%). Практически все квартиры без цены.","Эффект на backfill ekb_districts.median_price_per_m2: сработало только для 2 районов (Орджоникидзевский, Октябрьский). 6 районов остаются median=NULL.","Причина: kn-API не возвращает price для большинства квартир в sales/portal/table респонсе.","Реальный фикс: разобраться почему price=NULL (пробив chrome-devtools), возможно другой ключ в JSON. Или: брать price из sales_agg вместо per-flat."]}
{"type":"entity","name":"Backfill_District_Median_From_Kn_Flats","entityType":"code_module","observations":["Сырой SQL: UPDATE ekb_districts SET median = (PERCENTILE_CONT(0.5) FROM kn_flats JOIN kn_objects ON district_name) WHERE n>=30.","Результат 29.04.2026: Орджоникидзевский=205051 (n=233), Октябрьский=191786 (n=55). Для расчёта district_factor оживило 2 из 8 районов.","При вызове recommend_mix: Орджоникидзевский district_factor=1.03 (выше city median), Октябрьский=0.97 (ниже).","Остальные 6 районов — median NULL, district_factor=1.0 + warning. Блокир Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN."]}
{"type":"entity","name":"Component_Recommend_Page_Reorder_Apr29","entityType":"ui_component","observations":["frontend/src/app/analytics/recommend/page.tsx — реорганизация порядка секций.","Было: Velocity → Liquidity Chart → KPI strip (city-wide) → Buckets → Revenue → Sliders → Table → Comparable.","Стало: Headline → Velocity (с price slider) → SLIDERS MIX → Liquidity → District-KPI → Buckets → Revenue → Table → Comparable.","Причина: user 'хочу видеть как меняются параметры при изменении mix' — все контроли (цена+mix) выше результатов."]}
{"type":"entity","name":"Component_Recommend_District_KPI_Strip","entityType":"ui_component","observations":["Новый KPI-strip в page.tsx вместо старых city-wide дублей ('Район / Сделок / Weighted / Выручка' — все одинаковые между районами).","4 новых KPI: 'Конкуренты в районе' (с hint о scope), 'Sale_graph покрытие' (X ЖК / Y точек / fallback), 'District factor', 'Class multiplier'.","Все 4 меняются при переключении района. Старые city-wide вынесены в headline-плашку и velocity-panel."]}
{"type":"entity","name":"Cleanup_Unused_Vars_Recommend","entityType":"code_module","observations":["Убраны totalRevenue + weightedAvgPrice из page.tsx (были в useMemo но нигде не использовались после рефактора).","Single source of truth: backend.recommend_mix считает эти значения, фронт отображает из summary.headline и RecommendVelocityPanel."]}
{"type":"entity","name":"Pricing_Slider_Range_Expanded_Apr29","entityType":"policy","observations":["Диапазон Price ± slider: 0.85..1.15 (±15%) → 0.01..3.0 (0.99..+2.0 = 99%..+200%).","min=0.01 (НЕ 0) чтобы избежать pf^elasticity = ∞ (при elasticity=-1.5 и pf=0).","Pydantic schema: RecommendMixInput.price_factor Field(ge=0.01, le=3.0).","Inverse-mode 'Применить required_pf' тоже клампит на [0.01, 3.0].","Практически для CEO-демо: -50% в цене → velocity × 0.5^-1.5 = ×2.83 (в почти 3 раза быстрее), +100% → ×0.35."]}
{"type":"entity","name":"Limit_District_Geometry_Closed","entityType":"limitation","observations":["Дата закрытия: 29.04.2026.","Изначально: rosreestr_deals имеет только quarter_cad_number, без района. ekb_districts не имела PostGIS-полигонов.","Решение: Geo_District_Mapping_Apr29 (Overpass API → PostGIS → spatial-join через lat/lon ЖК). Обходим отсутствие cad_quarter→район маппинга через kn_objects как мост (lat/lon → district).","Per-district demand работает в recommend_mix: 4 запроса используют district_name = :dn."]}
{"type":"entity","name":"Limit_District_Median_Partial","entityType":"limitation","observations":["Частично решен Limit_District_Median_Null (29.04.2026): 2 из 8 районов имеют median (Орджоникидзевский 205051, Октябрьский 191786) из kn_flats.","Остальные 6 = NULL: kn-API возвращает price для всего 0.15% квартир (Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN).","Блокирующий fix: разобраться почему kn-API не отдаёт price (возможно другой ключ в JSON, или взять из sales_agg.price_avg).","Альтернативный путь (отложен): rosreestr_deals → cad_quarter → район через NSPD кадастровые полигоны."]}
{"type":"entity","name":"Session_GeoMapping_Apr29_2026","entityType":"event","observations":["Дата: 29.04.2026. Продолжение Session_Apr28_Calc_Scraper_Apr28_2026.","ГЛАВНОЕ: Geo_District_Mapping_Apr29 — PostGIS-полигоны 8 районов ЕКБ из OSM Overpass, backfill domrf_kn_objects.district_name, recommend_mix переведён на district_name = :dn (вместо addr ILIKE).","СДЕЛАНО:","1. Module_Fetch_Ekb_Districts (Overpass loader) + File_Ekb_Districts_Geojson_Cache + Schema_Ekb_Districts_Geom + Schema_Kn_Objects_District_Column + Module_Backfill_District_Names_Scraper.","2. Pattern_OSM_Overpass_Admin_Level (admin_level=9 для районов РФ).","3. Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed (4 места).","4. Module_Graceful_Obj_Class_Degrade (kn-API obj_class=NULL не валит фильтры).","5. Backfill_District_Median_From_Kn_Flats (2/8 районов).","6. Component_Recommend_Page_Reorder_Apr29 + Component_Recommend_District_KPI_Strip + Cleanup_Unused_Vars_Recommend.","7. Pricing_Slider_Range_Expanded_Apr29 (±15% → 99..+200%).","CLOSED: Limit_District_Geometry_Closed, Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed, Limit_District_Median_Partial.","OPENED: Bug_Kn_API_Obj_Class_Always_Null_OPEN, Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN.","ПРОД SCHEMA: 2 новые миграции применены: 56_schema_ekb_districts_geom.sql + 57_kn_objects_district.sql. ekb_districts.median обновлён для 2 районов.","ПРИОРИТЕТЫ: 1) Разобраться с obj_class/price из kn-API (оба ОПЕН бага). 2) NSPD GeoJSON cad-кварталов для rosreestr-маппинга. 3) Этильбарные тиры 1-3 предикта."]}
{"type":"entity","name":"Tier2_District_Macro_Factors_Apr29","entityType":"deliverable","observations":["Дата: 29.04.2026. Расширение recommend_mix тремя district-специфичными факторами + макро-контекст для CEO.","Факторы: sat_factor (зрелость рынка), trend_factor (ускорение/выхлаждение 6мо), poi_factor (развитость района).","Результат (Comfort, 50K м²): Орджоникидзевский 31 мес vs Академический 58 мес — разнос 1.9x при одинаковых вводных параметрах.","Macro context: ставка ИЖК 7.84% (Свердл, Янв 2026) в footer headline для CEO-легитимности."]}
{"type":"entity","name":"Module_District_Saturation_Factor","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _district_market_saturation(db, *, district_name).","Median sold% активных строящихся ЖК в районе из domrf_kn_sales_agg.perc.","Применение: sat_factor = 1 + (sold_median - 50) / 100 * 0.3 — ±15% при крайних (>50% зрелый → +bonus, <20% свежий → -penalty).","Требует ≥5 ЖК в районе с perc != NULL.","Данные (29.04.2026): Ленинский 48% (зрелый), Академический 38%, Кировский 29.5% (свежий). Разнос ~20пп."]}
{"type":"entity","name":"Module_District_Velocity_Trend","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _district_velocity_trend(db, *, district_name).","Ratio recent_6mo / prior_6mo realised из domrf_kn_sale_graph (apartments). H1 2025 vs H2 2025+.","Применение: trend_factor = clamp(ratio, 0.7, 2.0) — блокировка экстремумов (Академический raw 6.66 в начале 2025).","Данные: все 8 районов НАРАСТАЮТ (ratio 2.07..6.66) — H1 2025 был холодным. Когда наберём 24+ мес истории — числа станут дифференцированными.","UI: в KPI strip 🚀 (>1.5 рынок ускоряется) / → (стабильный) / ❄ (<0.8 остывает)."]}
{"type":"entity","name":"Module_District_Poi_Score","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _district_poi_score + _city_avg_poi_score.","Weighted POI count по РАЙОНУ: SUM(weight) per ЖК в радиусе 1000м, потом AVG по ЖК района.","Веса категорий: Метро 2.0, Транспорт 1.5, Медицина 1.3, Образование 1.2, Спорт 1.0, Продукты 0.8, Развлечения 0.7, Новостройки 0.0 (сами ЖК, не amenity).","Применение: poi_factor = 1 + (district / city_avg - 1) * 0.05 — ±5% влияние на ЦЕНЫ (не на velocity).","Сейчас ratios 0.99..1.02 — все районы ~city avg. Даст больше эффекта когда POI покрытие выравняется."]}
{"type":"entity","name":"Module_Current_Mortgage_Rate","entityType":"code_module","observations":["backend/app/services/analytics_queries.py :: _current_mortgage_rate.","SQL: title ILIKE 'Средневзвешенная ставка по ипотечным жилищным%' AND '%в рублях, %' AND value BETWEEN 1 AND 30.","Выдаёт 7.84% (Свердл, Янв 2026) — СО ЛЬГОТАМИ (семейная, IT, ДВ-ипотека входят в средневзвешенную).","Рыночная ставка без льгот ~20.5% (РБК, Янв 2026) — в БД НЕТ такой серии. UI footer явно пишет 'со льготами; рыночная ~20%'."]}
{"type":"entity","name":"Bug_Mortgage_Rate_5_57_Wrong_Match_Fixed","entityType":"bug","observations":["Симптом: scope.mortgage_rate_pct выдавал 5.57% вместо реальных 7.84%. User заметил: 'слишком маленькая'.","Причина: SQL filter title ILIKE '%ипотечн%жилищн%' слишком широкий — матчил 'ДОЛЮ ипотечных жилищных кредитов на ИЖС' (5.57%, это НЕ ставка). ORDER BY period DESC LIMIT 1 случайно брал эту строку.","Closed 29.04.2026 в Module_Current_Mortgage_Rate: title ILIKE 'Средневзвешенная ставка...' + '%в рублях, %' + value BETWEEN 1 AND 30. Теперь выдаёт 7.84%."]}
{"type":"entity","name":"Macro_Context_Mortgage_Rate_Apr29","entityType":"research","observations":["Дата: 29.04.2026. Проверено вебом (РБК, cbr.ru) по запросу user 'погугли про ставку'.","Рыночная ставка (без льгот) ПЕРВИЧКА Янв 2026: 20.49%. ВТОРИЧКА: 20.5%.","Средневзвешенная (с учётом льготных программ) Янв 2026: 7.6% по РФ, 7.84% по Свердл.","Ключевая ставка ЦБ ~21% (Ноябрь 2025+).","70% покупателей Comfort/Comfort+ подпадают под льготы (семейная основная — 6%); Business/Elite в большинстве берут рыночную ~20%.","БД cbr_mortgage_series имеет ТОЛЬКО средневзвешенную (с льготами), рыночной раздельно нет. UI footer явно уточняет это."]}
{"type":"entity","name":"Component_Tier2_KPI_Strip_Update","entityType":"ui_component","observations":["frontend/src/app/analytics/recommend/page.tsx — обновлён district-KPI strip.","4 KPI: Конкуренты / Sale_graph покрытие / Sold% медиана / Тренд 6 мес / Class × District (combined).","Sold% хинт: 'зрелый рынок' / 'свежий, мало распродано' / 'умеренная зрелость' с числом N ЖК.","Тренд: 🚀 (>1.5) / → (стабильный) / ❄ (<0.8) + ratio.","Class × District: перемноженный mult из 3 (class * district * poi) + breakdown в hint."]}
{"type":"entity","name":"Component_Headline_Macro_Footer","entityType":"ui_component","observations":["frontend/src/app/analytics/recommend/page.tsx — footer в headline-плашке под основной строкой.","Показывает: 📊 Средневзв. ИЖК 7.84% (Янв 2026, со льготами; рыночная ~20%) · POI 130/82 (выше среднего).","Отделён в визуале border-top с opacity 0.1, fontSize 12 · color #94a3b8."]}
{"type":"entity","name":"Component_Velocity_Panel_Methodology_Tier2","entityType":"ui_component","observations":["frontend/src/components/analytics/RecommendVelocityPanel.tsx — расширен methodology note.","Теперь показывает все 3 macro factors: 'sat ×0.96 (sold% 38) · trend ×2.00 (raw ×6.66 clamp 0.7..2.0) · POI ×1.02 (на цену)'.","Полная прозрачность для CEO: откуда каждая цифра."]}
{"type":"entity","name":"Limit_Trend_Always_Capped_OPEN","entityType":"limitation","observations":["Дата: 29.04.2026. trend_factor во всех 8 районах хлопается в max=2.0.","Причина: H1 2025 был холодным (мало сделок в свежевыпущенных ЖК) и sale_graph покрытие было тонким. recent_6mo / prior_6mo выходит всюду >2.0.","Решение отложено: когда наберём 24+ мес истории sale_graph (в мае/июне 2026), перевести trend window на H2 2025 vs H1 2026 — будут реальные ratios.","Пока эффект trend_factor одинаковый для всех районов (×2.0) — не дифференцирует их."]}
{"type":"entity","name":"Limit_POI_Factor_Tiny_OPEN","entityType":"limitation","observations":["Дата: 29.04.2026. poi_factor во всех районах в диапазоне 0.99..1.02.","Причина: POI покрытие равномерное по всем районам (1284 ЖК с POI из 1516 покрыты ровно), весовая формула даёт похожие числа.","Решение отложено: повысить sensitivity 0.05 → 0.15-0.20 или изменить формулу на percentile-rank вместо ratio. Или ввести разные weights для Comfort/Business (премиум покупатели больше ценят amenity).","POI категории: Новостройки 65K (игнор), Продукты 55K, Спорт 53K, Образование 48K, Медицина 5K, Развлечения 1.8K."]}
{"type":"entity","name":"Session_Tier2_Apr29_2026_Late","entityType":"event","observations":["Дата: 29.04.2026 днём. Продолжение Session_GeoMapping_Apr29_2026.","СДЕЛАНО:","1. Tier2_District_Macro_Factors_Apr29 — sat_factor + trend_factor + poi_factor + mortgage_rate.","2. 5 helpers: Module_District_Saturation_Factor + Module_District_Velocity_Trend + Module_District_Poi_Score + _city_avg_poi_score + Module_Current_Mortgage_Rate.","3. Component_Tier2_KPI_Strip_Update + Component_Headline_Macro_Footer + Component_Velocity_Panel_Methodology_Tier2.","4. Bug_Mortgage_Rate_5_57_Wrong_Match_Fixed + Macro_Context_Mortgage_Rate_Apr29 (верифицировано веб-поиском).","Smoke (Comfort, 50K м²): 5 районов, сроки 31..58 мес (разнос 1.9x). Орджоникидзевский 31, Кировский 34, Ленинский 39, Чкаловский 51, Академический 58. Чек 2.7-2.8 М ₽. Ликвидность 40/100.","OPEN BUGS: Limit_Trend_Always_Capped_OPEN (trend_factor везде max 2.0 пока sale_graph история тонкая), Limit_POI_Factor_Tiny_OPEN (±1-2% эффект).","OPEN BUG скрейпера (с прошлых сессий): Bug_Kn_API_Obj_Class_Always_Null_OPEN (kn-API отдаёт obj_class=NULL), Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN (kn-API отдаёт price для 0.15% квартир)."]}
{"type":"entity","name":"Bug_Velocity_Region_Wide_Rosreestr_Fixed_Apr29","entityType":"bug","observations":["Симптом: «Верх-Исетский · 5 000 м²»: за ~3.7 мес, темп 33.6 кв/мес, ликвидность 100/100 — фантастика для одного ЖК.","Корень: bucket_market_velocities в analytics_queries.py (lines 16851693) использовал rosreestr_deals/window per bucket по ВСЕМУ region_code=66. Window auto-extend до 24mo → ~159 deals/mo на регион → после /sqrt(80 competitors) × sat × trend = 33.8 кв/мес total. Точно совпадает с UI-цифрой.","footer показывал «Базовый темп 4.2 кв/мес (sale_graph: 40 ЖК / 720 точек)», но это число НЕ использовалось в bucket-расчёте — лишь декоративно.","Фикс (29.04.2026):","1) market_vel_pm = sale_graph median per ЖК района (либо rosreestr-fallback / N_competitors → per-ЖК proxy).","2) bucket_market_velocities = market_vel_pm × bucket.share / 100 (аллоцируем per-ЖК baseline на размерные сегменты).","3) Удалена нормировка /sqrt(competitors) — market_vel_pm уже per-ЖК.","4) Removed import math (больше не нужен).","Результат для 5K м² по 8 районам ЕКБ: 7.5..18 мес (вместо 3.7). Между районами реальный разброс 2.4x: Октябрьский 7.5 → Академический 18.","Closed by: 3 правки в backend/app/services/analytics_queries.py:16271739."]}
{"type":"entity","name":"Bug_Mortgage_5_57_Stale_Deploy_Apr29","entityType":"bug","observations":["Симптом: footer показывал 5.57% (старая неправильная), хотя _current_mortgage_rate был исправлен в Bug_Mortgage_Rate_5_57_Wrong_Match_Fixed.","Не код-баг: DB напрямую отдаёт 7.84% (Январь 2026, 'Средневзвешенная ставка по ипотечным жилищным... в рублях, %', value BETWEEN 1 AND 30 — корректная строка).","Backend на проде не передеплоен с фиксом → продолжает кешировать старый ответ.","Action: nginx reload / pm2 restart backend → подхватит новый код, footer покажет 7.84%.","Документировано в плане crispy-swinging-gadget.md секция Approach — B."]}
{"type":"entity","name":"NSPD_API_Endpoints_Apr29","entityType":"research","observations":["NSPD geoportal v2 API: nspd.gov.ru — публичная аналитика недвижимости РФ.","ВАЖНО: WAF блокирует не-РФ IP (HTTP 403 + 'Rule: ...'). Для скрейпа нужен российский egress.","chrome-devtools MCP не помогает обойти — sandboxed Chrome у Anthropic тоже блокируется (тот же IP).","ПРОВЕРЕННО РАБОТАЮЩЕЕ: same-origin fetch со страницы NSPD у пользователя — WAF пропускает, certs OK.","ENDPOINTS:","1. GET /api/geoportal/v2/search/geoportal?thematicSearchId={id}&query={text} — основной search."," thematicSearchId: 1=Объекты недвижимости, 2=Кадастровое деление, 4=Адм-тер деление, 5=Зоны и территории, 7=Терр зоны, 15=Комплексы."," query=cad-номер квартала: id=2 → 1 polygon квартала; id=1 → до 20 features (земля+здания+помещения+машино-места+сооружения) внутри квартала.","2. GET /api/aeggis/v4/{layer_id}/wms?REQUEST=GetFeatureInfo&BBOX=...&I=256&J=256&FEATURE_COUNT=10&INFO_FORMAT=application/json — векторные данные слоя."," FEATURE_COUNT > 10 → HTTP 500. Только 10 features per call.","3. POST /api/geoportal/v1/download/objects/csv — кнопка 'Скачать список'. CSV метаданных, не GeoJSON.","4. GET /api/geoportal/v1/layers-theme — список тематик (PKK, ARN, etc.).","5. GET /api/geoportal/v1/layers-theme-tree?themeId={id} — слои в тематике.","ТЕМАТИКИ:","- 1 (PKK): 63 слоя — Кадастровые округа/районы/кварталы (36071), Здания (36049), Объекты незавершенного строительства (36329), Кадастровая стоимость (37236).","- 665 (ARN): 12 слоёв — Объекты по площади 0-25/25-40/40-60/60-80/80-100/100+ м² (WMS+MVT)."]}
{"type":"entity","name":"Cad_Quarter_Scrape_Apr29","entityType":"deliverable","observations":["Дата: 29.04.2026. Цель — связать rosreestr_deals.quarter_cad_number ↔ domrf_kn_objects (lat/lon) через PostGIS spatial-join.","Schema: cad_quarters_geom (cad_number, geom MultiPolygon 4326) + cad_buildings (cad_num, geom geometry, cost_value, year_built, purpose, area, floors, addr).","ALTER domrf_kn_objects ADD cad_quarter, cad_building_num.","Pipeline (через debug-Chrome пользователя):","1. fetch /api/geoportal/v2/search/geoportal?thematicSearchId=2&query={cad} → polygon квартала","2. fetch /api/geoportal/v2/search/geoportal?thematicSearchId=1&query={cad} → 20 зданий + помещения + земля","3. Filter buildings by categoryName='Здания' AND cad_num LIKE '66:41:%' (исключить out-of-EKB).","4. Convert geometry to WKT (EPSG:3857), batch-INSERT в Postgres через mcp__postgres__execute_sql с ST_Transform→4326.","5. После полного scrape: backfill domrf_kn_objects.cad_quarter через ST_Contains.","Прогресс: schema готова, 5 quarters в БД (66:41:0105031, :0106002, :0106009, :0106021, :0106023). 669 осталось.","Estimate: 670 × 2 fetch × 700ms = 15-20 мин в browser + 134 × 5s INSERT = 12 мин = ~30 мин.","ВАЖНО: search id=1 включает здания из других округов (66:15, 66:36, 66:51 — Невьянский/В.Пышма/Красноуральск) с похожими суффиксами. Фильтр 'cad LIKE 66:41:%' обязателен.","Полные файлы артефактов: data/sql/58_schema_cad_quarters.sql, 58_fetch_cad_quarters_nspd.py (ineffective без РФ-IP), 59_backfill_obj_cad_quarter.sql, 60_v_zk_rosreestr_velocity.sql + data/raw/cad_quarter_list.txt."]}
{"type":"entity","name":"NSPD_Scrape_Complete_Apr30","entityType":"deliverable","observations":["Дата: 30.04.2026. Завершён полный скрейп NSPD кадастровых данных через debug-Chrome (обход WAF через same-origin XHR + JWT gosuslugi.ru auth).","ИТОГ: 709 cad-кварталов / 10590 зданий в БД. Покрытие свежих ДДУ-сделок Свердл (12mo): 91% (713/784).","Scope: ЕКБ (674 квартала из rosreestr_deals) + 43 пригорода с активными ДДУ за 12mo (Сысерть, Арамиль, В.Пышма, Сухой Лог, Богданович, Реж, Артёмовский).","Schema: cad_quarters_geom (cad_number PK, geom MultiPolygon 4326, raw_props jsonb) + cad_buildings (cad_num PK, geom Geometry, purpose, building_name, address, area, floors, year_built, year_commisioning, cost_value, registration_date, status, ownership_type, cultural_heritage, underground_floors, build_record_*, common_data_status, obj_type, raw_props jsonb).","Pipeline: chrome-devtools MCP browser → fetch NSPD endpoints (thematicSearchId=2 для квартала + =1 для зданий внутри) → save via 61_import_nspd_batch.py через SSH-tunnel localhost:15432.","Время: ~3-4 часа активной работы (с 60-90s drain интервалами + import batches).","Closed limitations: Limit_District_Geometry_Closed, Limit_District_Median_Partial (теперь rosreestr_deals → cad_quarter → ЖК работает).","Files: data/sql/58_schema_cad_quarters.sql, 61_import_nspd_batch.py (v2 with raw_props), data/raw/nspd_drain_*.jsonl + nspd_refetch_*.jsonl (50+ batch files)."]}
{"type":"entity","name":"NSPD_API_Endpoints_Reference","entityType":"reference","observations":["Дата: 30.04.2026. Полная карта NSPD API endpoints (из debug-Chrome обхода).","BASE: https://nspd.gov.ru","АУТХ: JWT через gosuslugi.ru SSO. JWT exp ~30 мин. Cookie: authAccessToken+authRefreshToken. Без auth — HTTP 403 на API (но статика проходит).","WAF: блокирует не-РФ IP на /api/* endpoints. chrome-devtools MCP sandboxed Chrome тоже блокируется (egress = Anthropic IP). РАБОЧИЙ ОБХОД: same-origin XHR со страницы nspd.gov.ru/map в браузере пользователя.","Endpoints:","1. GET /api/geoportal/v2/search/geoportal?thematicSearchId={id}&query={text}"," thematicSearchId: 1=Объекты недвижимости (земля+здания+помещения+маш-места+сооружения), 2=Кадастровое деление (квартал/район/округ), 4=Адм-тер деление, 5=Зоны, 7=Терр. зоны, 15=Комплексы."," query=cad-номер: id=2 → 1 polygon квартала; id=1 → до 90 features (по 20 на категорию) внутри квартала.","2. GET /api/aeggis/v4/{layer_id}/wms?REQUEST=GetFeatureInfo&BBOX=...&I/J=&FEATURE_COUNT=10 — векторные данные слоя по bbox+pixel. FEATURE_COUNT > 10 → HTTP 500.","3. POST /api/geoportal/v1/download/objects/csv — CSV-экспорт выбранных объектов (но не GeoJSON).","4. GET /api/geoportal/v1/layers-theme — список тематик.","5. GET /api/geoportal/v1/layers-theme-tree?themeId={id} — слои в тематике.","Тематики: 1 (PKK, 63 слоя — Кадастровые квартал=36071, Здания=36049, Объекты незавершенного строительства=36329, Кадастровая стоимость=37236), 665 (ARN=Аналитика рынка недвижимости, 12 слоёв — объекты по площади 0-25/25-40/40-60/60-80/80-100/100+ м² WMS+MVT).","Geometry SRID: EPSG:3857 (web mercator). На стороне БД ST_Transform(3857→4326).","ВАЖНО: search id=1 включает здания из других кадастровых округов с похожими суффиксами. Фильтр 'cad_num LIKE \"66:41:%\"' обязателен."]}
{"type":"entity","name":"Cad_Buildings_Schema_v2","entityType":"schema","observations":["Дата: 30.04.2026. cad_buildings (10590 строк) — итоговая схема после v2 extension.","Колонки структурированные:","- cad_num TEXT PK — кадастровый номер здания (66:41:0108043:59)","- quarter_cad_num TEXT — родительский квартал (3 первых сегмента)","- geom Geometry(Geometry, 4326) — Point/Polygon/MultiPolygon","- purpose TEXT — Многоквартирный дом / Жилое / Жилой дом / Нежилое / Гараж","- building_name TEXT, readable_address TEXT","- area NUMERIC, floors TEXT (например '10-18')","- year_built INTEGER, year_commisioning INTEGER","- cost_value NUMERIC — кадастровая стоимость ₽","- registration_date DATE","- status TEXT — 'Учтенный' (1679) / 'Ранее учтенный' (8148)","- ownership_type TEXT, cultural_heritage TEXT, underground_floors TEXT","- build_record_area NUMERIC, build_record_type TEXT","- common_data_status TEXT, obj_type TEXT","- raw_props jsonb — ПОЛНЫЙ options-объект NSPD (для будущих запросов)","Распределение purpose: Нежилое 4040 / Многоквартирный дом 3245 / Жилое 1567 / Гараж 559 / Жилой дом 601.","Cross-validation: NSPD кадастровая стоимость per м² ≈ 30-40K ₽/м², рыночная (sale_graph) 130-244K — разница в 3-5×. Premium 50-90% типично, аномалии (-34% Белая Башня) сигнализируют outlier."]}
{"type":"entity","name":"Cad_Quarter_Backfill_Apr30","entityType":"deliverable","observations":["Дата: 30.04.2026. Spatial-join: domrf_kn_objects.cad_quarter заполнен через ST_Contains(cad_quarters_geom.geom, lat/lon).","Coverage: 2262/2578 ЖК (88%) ЕКБ привязаны к cad_quarter, 237 уникальных кварталов используются.","По районам: Академический 96%, Октябрьский 93%, Железнодорожный 93%, Ленинский 88%, Чкаловский 87%, Кировский 87%, Орджоникидзевский 80%, Верх-Исет 69%.","По статусу: Строящиеся 357/442 (81%), Сданные 774/1073 (72%), Проблемные 1/2 (50%).","ЖК↔здание матч через ST_DWithin(50м): 349 ЖК сматчены с конкретным МКД из cad_buildings.","Топ-точные совпадения (ошибка 36-77м): ЖК «Сибирский сад» → 66:41:0603016:198, Атлас Ривер → 66:41:0508075:1406, Парковый квартал 2.0 → 66:41:0402030:2391 (yc=2025)."]}
{"type":"entity","name":"Sprint1_Plan_May2026","entityType":"plan","observations":["Дата создания плана: 30.04.2026. План реализации Sprint 1 (нед 1-2 мая).","Tier 1 — критичный путь:","A. NSPD-scraper индустриализация (~2 дня): Playwright + gosuslugi SSO auth → backend/app/services/scrapers/nspd_kn.py + Celery task scrape_nspd_region + nspd_scrape_runs table + crontab(day=20, month='2,5,8,11'). 80% переиспользование domrf_kn.py паттернов.","B. Recommend_mix Tier 3 (~3 дня): per-bucket elasticity вместо скаляра. SQL window-functions по area_bucket + frontend per-bucket curve.","C. NSPD кадастр vs sale_graph cross-check UI (~1 день): premium % колонка + warning badge для аномалий >50%.","D. Issue #4 SENTRY_RELEASE (~30 мин): SSH→.env.runtime + sentry_sdk init.","Итого Sprint 1: ~7 дней работы.","План в C:\\Users\\user\\.claude\\plans\\next-iteration-roadmap.md."]}
{"type":"entity","name":"Sprint2_Stage1_Generative","entityType":"plan","observations":["Sprint 2 (нед 3-6): Stage 1 Generative MVP — продуктовое ядро, делает gendesign продаваемым.","Issue #5 Stage 1a (~5 дней): app/services/generative/geometry.py (Shapely парсер GeoJSON, отступы, placement grid), Pydantic ConceptInput/Output, frontend Leaflet drag-drop + 3 таба-варианта (заглушки).","Issue #12 Stage 1b (~5 дней): Greedy алгоритм 3 стратегии (max_area/max_insolation/balanced) с STRtree коллизиями. Цель: 3 варианта ≤15сек на 1 га. Frontend визуализация корпусов + ТЭП метрики.","Issue #6 Stage 1c (~6 дней): services/generative/teap.py + financial.py (revenue/cost/IRR), экспортеры PDF/Excel/DXF, API POST /concepts/{id}/export. Завершение Stage 1.","Итого: ~16 дней. После этого Stage 1 = продаваемый артефакт для встреч с инвесторами."]}
{"type":"entity","name":"Sprint3_Stage2_SiteFinder","entityType":"plan","observations":["Sprint 3 (нед 7-10): Stage 2 Site Finder MVP — конец продуктового vision.","Issue #7 Stage 2a (~5 дней): site_finder/parser.py (ПКК Rosreestr, GeoAlchemy2 Parcel модель, ≥1000 участков ЕКБ) + workers/sales_tracker.py (шахматки топ-7 застройщиков: Атомстрой, Брусника, ТЭН, Стройтек, Прогресс, УГМК, КОРТРОС).","Issue #8 Stage 2b (~5 дней): scorer.py (3-4 критерия: distance_to_center, POI_density, district_price + опц. velocity_score), POST /parcels/search ≤500мс, frontend Mapbox color-graded markers + sidebar filters.","Issue #9 Stage 2c (~3 дня): кнопка 'Обсчитать концепцию' на карточке участка → pipe в /concepts. + Реестр ПО подача (60-180 дней). + финмодель 5-летняя для инвест-deck.","Pre-existing data: NSPD cad_quarters (709 кварталов) переиспользуем как один из источников для site_finder. ПКК даст vri+address+другие слои."]}
{"type":"entity","name":"GitHub_Issues_Open_Apr30","entityType":"reference","observations":["8 открытых issues на 30.04.2026.","#3 Selectel/Yandex S3 backup setup — ❌ ИСКЛЮЧЕНО пользователем (не делаем).","#4 SENTRY_RELEASE deploy.yml tracking — Tier 4 (~30 мин).","#5 Stage 1a Shapely service + API contract — Sprint 2.","#6 Stage 1c TEAP + finmodel + экспорты PDF/Excel/DXF — Sprint 2.","#7 Stage 2a ПКК parser + sales_tracker — Sprint 3.","#8 Stage 2b Scoring + API + UI — Sprint 3.","#9 Stage 2c Integration + реестр ПО + финмодель — Sprint 3.","#11 Антон onboarding к knowledge-graph (Claude Desktop + MCP) — Tier 4 (~30 мин документации).","#12 Stage 1b Greedy алгоритм 3 стратегии STRtree — Sprint 2."]}
{"type":"entity","name":"Open_Limitations_Apr30","entityType":"limitation","observations":["Дата: 30.04.2026. Открытые ограничения после NSPD-pipeline.","1. Limit_Trend_Always_Capped_OPEN — все 8 районов ЕКБ имеют raw trend ratio 5+ (capped к 2.0). Решится через 6-12 мес sale_graph истории. Не действуем сейчас.","2. Limit_POI_Factor_Tiny_OPEN — POI ratio 0.99-1.02 везде (равномерное распределение POI). Можно увеличить вес с 5% до 10% или добавить distance-weighting к метро.","3. Bug_Kn_API_Obj_Class_Always_Null_OPEN — kn-API НЕ отдаёт obj_class для всех 3032 ЖК Свердл. Решение: fallback на yandex_realty_zk.obj_class через name-match (~1 день).","4. Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN — kn-API даёт price для 0.15% квартир. ekb_districts.median для 6 районов NULL. Workaround есть в recommend_mix (sale_graph baseline). Дополнительно: можно взять median из cad_buildings.cost_value (но это кадастр, не рыночная).","5. ✅ CLOSED: Limit_District_Geometry_Closed (через OSM ekb_districts), Limit_District_Median_Partial (через cad_quarter mapping)."]}
{"type":"entity","name":"Excluded_Items_User_Pref","entityType":"policy","observations":["Дата: 30.04.2026. Пользователь явно исключил из roadmap.","❌ Issue #3 Selectel/Yandex S3 backup — пропускаем.","❌ Любое перемещение infra в Yandex Cloud / Selectel — пропускаем.","❌ pg_dump → cloud — пропускаем.","Причина не указана. Если потребуется ДР-стратегия — спросить отдельно."]}
{"type":"entity","name":"Session_End_Apr30_2026","entityType":"event","observations":["Дата: 30.04.2026. Длинная сессия (~5+ часов): NSPD scrape end-to-end + planning.","Главное:","1. NSPD_Scrape_Complete_Apr30 — 709 кварталов / 10590 зданий, 91% покрытие свежих ДДУ.","2. Cad_Buildings_Schema_v2 — расширили схему raw_props jsonb + 8 новых колонок.","3. Cad_Quarter_Backfill_Apr30 — spatial-join 2262/2578 ЖК (88%).","4. Cross-check: NSPD кадастр vs ДОМ.РФ рынок — premium 50-90% типично.","5. Sprint1_Plan_May2026 + Sprint2_Stage1_Generative + Sprint3_Stage2_SiteFinder — план на 10-12 недель до Phase 0 финиша.","OPEN на следующую сессию: Sprint 1 task A (NSPD scraper индустриализация Playwright+Celery).","Артефакты: ~50 JSONL drain-файлов в data/raw/, обновлённый 61_import_nspd_batch.py, план в C:\\Users\\user\\.claude\\plans\\next-iteration-roadmap.md.","ИНСАЙТ: rosreestr_deals.realestate_type='002001003000' даёт 91% покрытие за 12mo. Sale_graph ДОМ.РФ остаётся золотым стандартом для velocity (rosreestr недополнен — для топ-ЖК показывает 0.1 кв/мес против реальных 16-45 из sale_graph).","Pipeline через debug-Chrome работает но мануальный — индустриализация в Sprint 1."]}
{"type":"entity","name":"Objective_Integration_May07_2026","entityType":"deliverable","observations":["Дата: 07.05.2026. Интеграция с api.objctv.ru (Объектив) — внешний B2B аналитический API с per-flat данными по новостройкам РФ.","Цель: получить data feed богаче чем ДОМ.РФ kn-API: per-flat статус/цена/банк/дата регистрации + per (месяц × корпус × room-bucket) агрегаты для recommend_mix.","Архитектура: settings.objective_api_key → ObjectiveClient (httpx + Bearer-токен в Redis с in-memory fallback) → 4 канонические отчёты → objective_raw_reports (jsonb) → 70_parse_objective_raw.py → objective_corpus_room_month + objective_lots + objective_lots_history.","Celery-task tasks.scrape_objective.sync_objective_group: еженедельно пн 05:00 МСК (settings.objective_sync_cron='0 5 * * mon'). Тянет 2 рабочих отчёта (Сводные/Корпуса + Поквартирные/Лоты), сохраняет raw, сразу же парсит через late-import парсера 70.","Smoke-test 07.05 подтвердил: Парк Культуры (1 ЖК × 7 дней) → corp_sum 8 строк (13.5 KB) + lots_pf 563 квартир (818.8 KB). Парсер dry-run обработал все строки без warning.","ОТЛИЧИЕ ОТ ДОМ.РФ kn-API: точные per-flat поля — Статус, Цена за м2, Дата договора, Дата регистрации, Тип сделки (ДДУ/ДКП), Банк (ипотека!), Тип обременения. Это ×100 точнее domrf_kn_flats и даёт банковские предпочтения покупателей по проектам.","Открывает: velocity-anomaly detection (issue #17), elasticity per-flat-history (Tier 4 точнее regression × лет), competitor-360 (issue #19), mortgage-rate sensitivity (issue #20).","ОГРАНИЧЕНИЯ ТАРИФА: 2 из 4 канонических отчётов возвращают HTTP 500 'An unexpected error occurred' — Сводные/Лоты и Поквартирные/Корпуса. Не блокер: оба нужных получаем.","СТАТУС: код готов и протестирован локально (dry-run). Не применено: schema 68 на проде (mcp postgres был на svc_mosgas — нужно вручную через SSH-tunnel localhost:15432). OBJECTIVE_API_KEY в backend/.env прода не прописан.","Файлы: backend/app/services/scrapers/objective.py (ObjectiveClient) · backend/app/workers/tasks/scrape_objective.py (Celery task с inline-парсингом) · backend/app/workers/celery_app.py (beat schedule) · data/sql/68_schema_objective.sql v2 · data/sql/69_objective_smoke.py · data/sql/69b_objective_minimal.py · data/sql/70_parse_objective_raw.py."]}
{"type":"entity","name":"Module_Objective_Client","entityType":"code_module","observations":["backend/app/services/scrapers/objective.py — HTTP-клиент к api.objctv.ru.","Auth: GET /Users/User/GetToken?apiKey=<KEY> → {token: '...'} (~30 мин TTL). Bearer на /v2/Report/GetReport.","Кеширование токена: Redis (ключ 'objective:bearer_token', TTL settings.objective_token_ttl_seconds=25*60) + in-memory fallback _TOKEN_MEMORY_CACHE (когда Redis недоступен — локальные скрипты, сетевой сбой). Лог про Redis печатается ОДИН раз на инстанс (флаг _redis_warned), не спамит.","Rate-limiting: _DEFAULT_RATE_MS=500мс между запросами. Ретраи: 3 попытки на 401/429/502/503/504. Backoff на 429: 30, 60, 120, 240с (потолок 300с). Слушает Retry-After header если присутствует.","401 → один раз форс-рефреш токена; если повтор — ObjectiveAuthError. 429/5xx → exponential backoff. Брotli accept по дефолту в Accept-Encoding (их рекомендация).","Публичные методы: report_corpuses_summary, report_lots_summary, report_corpuses_per_flat, report_lots_per_flat. Универсальный get_report() с явными именованными параметрами (report_section, report_type, report_name, group_name, complex_name, start_date, end_date, use_ddu, use_dkp, page='Отчеты', v2=True).","Date format Объектива: YYYY.MM.DD (точка-разделитель!) — _fmt_date конвертит из date/str.","fetch_with_raw_log() — one-shot helper для smoke-сценариев и backfill: вызывает <fn_name>(**kwargs), сохраняет raw JSON в файл если save_dir."]}
{"type":"entity","name":"Module_Objective_Parser","entityType":"code_module","observations":["data/sql/70_parse_objective_raw.py — парсер raw → normalized слой Объектива.","Режимы: --file-corp-sum/--file-lots-pf (локальные JSON, smoke без БД, --dry-run) | --raw-id N (один объект из objective_raw_reports) | --latest-run (все unparsed raw из последнего objective_scrape_runs.run_id).","Эвристика detect_kind() по полям первого row payload: 'corp_sum' если ['Месяц','Корпус','Объем предложения, шт.'] · 'lots_pf' если ['Id','Номер лота','Площадь, м2(ПД)']. None → skip с warning.","Helpers: _parse_ru_month('апрель-2026' → date(2026,4,1)) · _parse_iso_date · _to_int/_to_num · _normalize_rooms('студия'→0, '1'→1, …'5+'→5) · _parse_pct('17%'→17) · _parse_bool_yes('да'/'нет' → True/False).","parse_corp_sum: маппит ~30 полей → INSERT в objective_corpus_room_month с ON CONFLICT (report_month, group_name, project_name, corpus_name, room_bucket) DO UPDATE (right move — отчёт за месяц уточняется неделя-к-неделе пока месяц не закрыт).","parse_lots_pf: маппит per-flat → INSERT в objective_lots с ON CONFLICT (objective_lot_id) DO UPDATE + INSERT в objective_lots_history с ON CONFLICT (objective_lot_id, snapshot_date) DO NOTHING (один снимок per день — повторный sync в тот же день не создаёт дубль).","Late-import используется в Celery-task: importlib.util.spec_from_file_location → exec_module. Это позволяет inline-парсинг сразу после save_raw без копирования кода в backend.","Smoke 07.05 на локальных файлах: corp_sum 8 rows + lots_pf 563 lots / 563 history rows — все отработали без warning'ов про обязательные поля."]}
{"type":"entity","name":"Schema_Objective_v2_May07","entityType":"infrastructure","observations":["data/sql/68_schema_objective.sql v2 (07.05.2026) — ВЫРОВНЕНА по реальным полям payload-ов вместо изначальных гипотез.","Таблицы (6): objective_scrape_runs (журнал) · objective_raw_reports (jsonb payload) · objective_corpus_room_month (long-формат, заменяет старую objective_oks) · objective_lots (UPSERT по objective_lot_id) · objective_lots_history (append-only weekly snapshots) · objective_complex_mapping (Objective.ComplexName ↔ domrf_kn_objects.obj_id с is_reviewed).","objective_corpus_room_month: UNIQUE (report_month, group_name, project_name, corpus_name, room_bucket). Колонки: capacity по ПД (lots_pd_count/area), сделки ДДУ/ДКП/всего (по 7 метрик каждое), offer (count/area/sum_mln_rub/avg_price_thousand_rub_per_m2). Ключ инсайт: одна строка = (месяц × корпус × room_bucket) — long-формат, не per-corpus как было задумано в v1.","objective_lots: UNIQUE (objective_lot_id). Поля per-flat: 3 источника комнат (rooms_dev_site/rooms_pd/rooms_objective + нормализованный rooms_int), 2 площади (dev_site/pd), полный pricing (calculated_total/per_m2/offer_total/delta_rub/delta_pct + методы и даты), полный deal (contract/registration_date/contract_type/buyer_type/registration_number), encumbrance/mortgage (encumbrance_type/bank_name/encumbrance_start_date/egrn_actual_date).","objective_lots_history: UNIQUE (objective_lot_id, snapshot_date) — сами строим weekly timeline через INSERT при каждом sync (Объектив не отдаёт per-day price/status timeline в одном вызове, поэтому накапливаем сами). Для elasticity (точность × лет) и velocity-anomaly detection.","objective_complex_mapping: связь Objective.ComplexName/objective_project_id ↔ domrf_kn_objects.obj_id. is_reviewed=TRUE — человек подтвердил соответствие.","Размеры (оценка для Свердл.обл): corpus_room_month ~5K rows/мес (~250 ЖК × 5 корпусов × 5 mix × 1 мес), lots ~50K rows (~250 ЖК × 200 квартир), lots_history +50K rows/нед.","Применять: psql через SSH-tunnel localhost:15432 (mcp postgres был воткнут не в ту БД 27.04 → ручной apply). Идемпотентно через IF NOT EXISTS."]}
{"type":"entity","name":"Objective_API_Findings_May07","entityType":"research","observations":["Дата: 07.05.2026. Эмпирические находки об api.objctv.ru через локальные пробы (data/sql/69b_objective_minimal.py).","ENDPOINTS: GetToken на /Users/User/GetToken?apiKey=<KEY> → JSON {token: '...'}. GetReport на /v2/Report/GetReport?Page=Отчеты&ReportSection=Объединенные данные&ReportType=...&ReportName=...&GroupName=...&[ComplexName]&[StartDate]&[EndDate]&[UseDdu]&[UseDkp]. Auth: Authorization: Bearer <token>. Date format: YYYY.MM.DD (точка-разделитель).","ФОРМАТ ИМЕНИ ЖК: ComplexName требует БЕЗ префикса 'ЖК' и БЕЗ кавычек. Пример: 'Парк Культуры' → 200 OK, 'ЖК \"Парк Культуры\"' → HTTP 500. Проверено 07.05 на 2 запросах подряд.","PAYLOAD ОБЁРНУТ В {result: [...]}, не голый список — все ответы такие.","ДОСТУПНЫЕ НА ТАРИФЕ ОТЧЁТЫ (2 из 4): ✅ Сводные/Корпуса (per месяц × корпус × room_bucket) · ✅ Поквартирные/Лоты (per-flat snapshot с Id-stable). HTTP 500 'An unexpected error occurred' на: Сводные/Лоты, Поквартирные/Корпуса. Гипотезы: тариф / косяк бэка / неправильные параметры (попробовать без ComplexName, попробовать с/без StartDate).","RATE-LIMIT: жёсткий — 500мс между запросами недостаточно, нужен ~3000мс + пауза 15с между отчётами (default в скрипте 69b после фиксов). Иначе HTTP 429 на 2-м запросе. Backoff на 429 респектит Retry-After header.","ОТКЛИК: первый запрос отчёта может занимать 18-52 секунды (отчёт реально считается на бэке Объектива). Возможно у них лимит 1 concurrent request — с маленьким inter-delay прилетает 429.","REDIS LOCAL: на локальной машине Redis недоступен (редис только в docker compose) → in-memory fallback токена в ObjectiveClient критичен.","ПОЛЯ ИЗ corp_sum (Парк Культуры): Месяц (текст 'апрель-2026'), Проект, Девелопер ('PRINZIP'), Район ('Автовокзал'), Класс ('Комфорт'), Корпус ('1.1'), 'Количество комнат (Данные Объектива)' (студия|1|2|3), 'Лотов по ПД, шт.', 'Площадь по ПД, м2.', 7 метрик ДДУ × 7 метрик ДКП × 7 метрик 'всего' (count, count_priced, vol, vol_priced, sum_priced_млн_Р, avg_price_тыс_Р/м2, avg_area_м2), Объем предложения шт/м2, Суммарная стоимость лотов в продаже млн.Р, Средняя цена м2 лота в продаже тыс.Р/м2. NB: цены в ТЫС.Р/м2, не Р/м2; стоимости в МЛН.Р.","ПОЛЯ ИЗ lots_pf (per-flat, 563 квартир в Парк Культуры): Id (stable Objective lot_id, 1965382), 'Id проекта' (3802), Проект/Девелопер/Город/Район/Корпус/Адрес/Класс/Секция/Этаж/Номер лота/'Вид помещения' (квартира|нежилое|паркинг|кладовая), Готовность ('17%'), 'Стадия строительства' (строящийся), 'Отделка по корпусу' (под чистовую), Статус (резерв|свободна|продан|бронь), Продано (да/нет), 3 источника комнат, 2 площади (Сайт девелопера/ПД), полный pricing block (Расчетный бюджет, Цена за м2, Цена предложения, Дельта Р/%, Способ определения цены, Дата установки/актуальности цены), полный deal block (Дата договора, Дата регистрации, Тип сделки ДДУ|ДКП, Тип покупателя, Номер регистрации), encumbrance (Тип обременения, Банк, Дата начала обременения, Дата актуальности данных из ЕГРН).","ИНСАЙТ ДЛЯ РЕКОММЕНДА: Сводные/Корпуса УЖЕ даёт нам монетизированную monthly history per (corpus, room_bucket) — не надо строить из sale_graph + median area. Это подменяет половину recommend_mix без всяких регрессий.","ИНСАЙТ ДЛЯ ИПОТЕКИ: lots_pf.Банк = stable банковская атрибуция per flat. За 6 мес weekly sync получим ground-truth статистику ипотечных предпочтений по проектам/девелоперам/районам Свердл.обл — нет в открытых источниках."]}
{"type":"entity","name":"Session_End_May07_2026","entityType":"event","observations":["Дата: 07.05.2026. Сессия после возвращения юзера ('я вернулся давай вспомним на чем остановились'). Continued работу над Objective integration после context compaction.","СДЕЛАНО ЗА СЕССИЮ:","1. Объяснил юзеру где остановились: scaffold Objective integration был готов (settings, ObjectiveClient, schema 68 v1, Celery task, smoke-script), но не применён и не протестирован.","2. Создал data/sql/69b_objective_minimal.py — минимальный probe (4 отчёта × 1 ЖК × 7 дней) с CLI-флагами (--complex, --no-complex, --group, --days, --only).","3. Юзер запустил 1-й раз: получили формат имени ЖК ('Парк Культуры' без префикса/кавычек) + 429 на 2-м отчёте (Redis недоступен локально → новый GetToken на каждый запрос → rate-limit).","4. Фикс in-memory fallback токена в ObjectiveClient + дефолт --complex без префикса + datetime.utcnow→timezone.aware. Запуск 2 — снова 429 (rate-limit после первого отчёта).","5. Доб --inter-delay 15s между отчётами + --rate-ms 3000ms + Retry-After header + backoff 30/60/120 в клиенте. Запуск 3 — получили 2 рабочих отчёта (corp_sum 8 строк, lots_pf 563 квартиры). 2 других вернули HTTP 500.","6. Прочитал оба payload-а — обнаружил расхождения с schema 68 v1: corp_sum в long-формате (не per-corpus), lots_pf имеет stable Id + богатые поля (банк! 3 источника комнат! полный deal/encumbrance block).","7. ПЕРЕПИСАЛ 68_schema_objective.sql v2 под реальную структуру: objective_oks → objective_corpus_room_month, расширенная objective_lots с UNIQUE objective_lot_id, append-only objective_lots_history с UNIQUE (lot_id, snapshot_date).","8. Написал data/sql/70_parse_objective_raw.py — полный парсер с эвристикой detect_kind, helpers _parse_ru_month/_normalize_rooms/etc., 3 режима (--file/--raw-id/--latest-run). Smoke на локальных файлах: 8 corp + 563 lots без warning.","9. Обновил Celery-task scrape_objective: убрал 2 нерабочих отчёта (HTTP 500 на тарифе), добавил late-import парсера 70 для inline-нормализации сразу после save_raw, обновил _heartbeat/_finish_run новыми счётчиками (rows_corpus_room/rows_lots/rows_history).","OPEN на следующую сессию: применить schema 68 v2 на проде (вручную через SSH-tunnel localhost:15432, mcp postgres до сих пор воткнут не в gendesign) · прописать OBJECTIVE_API_KEY в backend/.env прода · реальный прогон Celery-task (sync_objective_group) на проде с группой 'Екатеринбург' (без ComplexName-фильтра, по всему городу) · обновить knowledge graph (этот entity).","ПРИОРИТЕТЫ ПОСЛЕ APPLY: 1) Прогон без ComplexName на ЕКБ — сколько rows? Объём lots_pf может быть огромным (~50K квартир × ~2KB). 2) Исследовать почему Сводные/Лоты + Поквартирные/Корпуса возвращают 500 (попробовать варианты params без ComplexName / с/без StartDate). 3) Спросить саппорт Объектива.","ИНСТРУМЕНТАРИЙ ПРОВЕРКИ: cd backend; OBJECTIVE_API_KEY=<key> uv run python -X utf8 ../data/sql/69b_objective_minimal.py [--no-complex --days 3 | --only corp_sum]. Сохраняет в data/raw/objective_test/<timestamp>/.","ФИНАЛЬНЫЕ файлы изменены 07.05: backend/app/services/scrapers/objective.py · backend/app/workers/tasks/scrape_objective.py · data/sql/68_schema_objective.sql · data/sql/69b_objective_minimal.py (новый) · data/sql/70_parse_objective_raw.py (новый)."]}
{"type":"entity","name":"SiteFinder_v0_2_May08","entityType":"build","observations":["Дата импорта в репо: 8 мая 2026 (вайб-код вёлся с начала мая, коммит 97b19a0 на main)","Название: GenDesign Parcel Scoring v2 (из server.py title), локальный коднейм Site Finder. Путь в репо: site-finder/","Бэкенд: однофайловый FastAPI server.py (~85 KB), 35 эндпоинтов. Основные: GET /api/sites, /api/site/{id}, /api/districts, /api/district-polygons, /api/macro, /api/audiences, /api/district-velocity-trend/{district}, POST /api/analyze. Ключевая оптимизация: в ОП Екб используется кэш 9479 OSM POI вместо Overpass-запроса (~30с -> <100мс)","Данные: SQLite analysis.db = 340 МБ (не в git, регенерируется пайплайном). Объёмы: 380 ЖК, 316 тыс site-POI пар, 303 тыс квартир с Объектива. Схема в db_init.py","Пайплайн сборки данных: 12 скриптов 01_load_sites.py -> 02_fetch_pois.py -> 03_score.py -> 04_report.py -> 05_objective_pull.py -> 06_match_economics.py -> 07_objective_full_pull.py -> 08_enrich_economics.py -> 09_macro_and_trend.py -> 10_score_v2.py -> 11_refetch_pois_extended.py -> 12_more_pois.py","Фронт: статика в static/. index.html около 3500 строк (Leaflet UI: карта + 11 табов + 4 модалки), sw.js — Service Worker для кэша тайлов карты. Не Next.js — ванильный HTML/JS","Кэши в репо: cache/ekb_admin_districts.geojson (148K, адм-районы Екб), cache/jk_polygons.geojson (592K, полигоны ЖК), cache/parcel_polygons/ (drop-zone для ручно выгруженных с nspd.gov.ru полигонов, README внутри), cache/geocode_cache.json (тёплый кэш геокодинга). НЕ в git: cache/objective_raw (1.2 GB), cache/osm_buildings_all.geojson, cache/overpass_raw.json","Production: сайт https://gendsgn.ru/sf/ (лендинг), https://gendsgn.ru/sf/app.html (приложение). Сервер: /opt/gendesign/site-finder/, Docker-контейнер gendesign-site-finder-1","Production memory path: /opt/gendesign/memory/memory-gendesign.jsonl (отличается от локального ~/.aim/ на macOS и C:\\mcp\\.aim\\ на Windows). Для полной синхронизации нужен такой же watcher на проде (сейчас реализован только для anton@macOS)","Контраст с MVP_Scope_AreaSelect_Apr25: этот билд — фактический Site Finder в проде (скоринг участков по POI/экономике/макро), но решение от 25 апреля откладывало Site Finder в Пост-MVP. Нужно сверить: (а) Site Finder всё-таки остаётся в MVP в виде этого прода, (б) он эксплораторский прототип параллельно основному MVP, (в) решение от 25 апр отменено фактически"]}
{"type":"relation","from":"Project_GenDesign","to":"TechStack_v2.2","relationType":"uses"}
{"type":"relation","from":"Project_GenDesign","to":"NorthStar_DiscoveryMVP","relationType":"targets"}
{"type":"relation","from":"Project_GenDesign","to":"Phase0_DiscoveryMVP","relationType":"currently_executes"}
{"type":"relation","from":"Phase0_DiscoveryMVP","to":"NorthStar_DiscoveryMVP","relationType":"delivers"}
{"type":"relation","from":"Validation_Findings_Apr25","to":"Project_GenDesign","relationType":"reviews"}
{"type":"relation","from":"Validation_Findings_Apr25","to":"TechStack_v2.2","relationType":"validates"}
{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Project_GenDesign","relationType":"strengthens"}
{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"DataSources_Pricing_Apr25","relationType":"extends"}
{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Phase0_DiscoveryMVP","relationType":"modifies"}
{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Stages_MVP_v1","relationType":"amends_stage_2a"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"Stages_MVP_v1","relationType":"supersedes"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"WorkSplit_Generative_Stage1","relationType":"needs_revision"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"SalesTracking_Strategy_Apr25","relationType":"depends_on"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"DataSources_Pricing_Apr25","relationType":"depends_on"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"Project_GenDesign","relationType":"reshapes"}
{"type":"relation","from":"Domain_Setup_Apr26","to":"Project_GenDesign","relationType":"infrastructure_for"}
{"type":"relation","from":"Domain_Setup_Apr26","to":"Hosting_Decision_Apr25","relationType":"extends"}
{"type":"relation","from":"Sentry_Setup_Apr26","to":"Project_GenDesign","relationType":"monitors"}
{"type":"relation","from":"Sentry_Setup_Apr26","to":"Phase0_DiscoveryMVP","relationType":"infrastructure_for"}
{"type":"relation","from":"OpsBundle_Apr26","to":"Project_GenDesign","relationType":"infrastructure_for"}
{"type":"relation","from":"OpsBundle_Apr26","to":"Stages_MVP_v1","relationType":"prepares_for"}
{"type":"relation","from":"Production_Wipe_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"refreshed_state_of"}
{"type":"relation","from":"DockerOps_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"extends"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"Domain_Setup_Apr26","relationType":"completes"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"Phase0_DiscoveryMVP","relationType":"infrastructure_milestone_for"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"Project_GenDesign","relationType":"deploys"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"DataSources_Pricing_Apr25","relationType":"supersedes"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"unblocks"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"SalesTracking_Strategy_Apr25","relationType":"downgrades"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"Stages_MVP_v1","relationType":"amends_stage_2a"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"Project_GenDesign","relationType":"data_strategy_for"}
{"type":"relation","from":"DomRF_Tab11_MortgageStats_Apr26","to":"DomRF_Tab10_MortgageRates_Apr26","relationType":"paired_with"}
{"type":"relation","from":"DomRF_API_PortalAnalytics_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_API_PortalKn_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_API_KnObject_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_API_KnFlats_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_API_KnDicts_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_API_Files_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_API_Registries_Apr26","to":"DomRF_Host_Apr26","relationType":"hosted_on"}
{"type":"relation","from":"DomRF_Tab1_HousingIndicators_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab2_LaunchAndCommissioning_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab4_DevelopersDashboard_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab7_ReadyConstruction_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab8_Quartirografia_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab9_BuildingCommissioning_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab11_MortgageStats_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_Tab1_HousingIndicators_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab3_ProjectFinance_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab5_Escrow_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab6_Realization_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab10_MortgageRates_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab12_StatRows_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_PerFlat_Schema_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"describes_schema_of"}
{"type":"relation","from":"DomRF_PerFlat_ETL_Apr26","to":"DomRF_PerFlat_Schema_Apr26","relationType":"uses_schema"}
{"type":"relation","from":"DomRF_PerFlat_VelocityTracker_Apr26","to":"DomRF_PerFlat_Schema_Apr26","relationType":"uses_field"}
{"type":"relation","from":"DomRF_PerFlat_VelocityTracker_Apr26","to":"DomRF_Tab6_Realization_Apr26","relationType":"alternative_to"}
{"type":"relation","from":"DomRF_PerFlat_VelocityTracker_Apr26","to":"DomRF_Tab7_ReadyConstruction_Apr26","relationType":"alternative_to"}
{"type":"relation","from":"DomRF_ExtractFlow_Objects_Apr26","to":"DomRF_API_PortalKn_Apr26","relationType":"step_1_uses"}
{"type":"relation","from":"DomRF_ExtractFlow_Objects_Apr26","to":"DomRF_API_KnObject_Apr26","relationType":"step_2_uses"}
{"type":"relation","from":"DomRF_Object_ETL_Apr26","to":"DomRF_ExtractFlow_Objects_Apr26","relationType":"implements"}
{"type":"relation","from":"DomRF_Object_ETL_Apr26","to":"DomRF_PerFlat_ETL_Apr26","relationType":"complements"}
{"type":"relation","from":"DomRF_BrokenEndpoints_Apr26","to":"DomRF_API_KnObject_Apr26","relationType":"failed_alternatives_to"}
{"type":"relation","from":"DomRF_Spec_SJS_v130","to":"DomRF_OfficialAuth_Apr26","relationType":"uses_auth"}
{"type":"relation","from":"DomRF_Spec_NSI_v101","to":"DomRF_OfficialAuth_Apr26","relationType":"uses_auth"}
{"type":"relation","from":"DomRF_Spec_UOPO_v102","to":"DomRF_OfficialAuth_Apr26","relationType":"uses_auth"}
{"type":"relation","from":"DomRF_Spec_APF_v22","to":"DomRF_OfficialAuth_Apr26","relationType":"uses_auth"}
{"type":"relation","from":"DomRF_OfficialVsFront_Comparison_Apr26","to":"DomRF_Spec_SJS_v130","relationType":"compares"}
{"type":"relation","from":"DomRF_OfficialVsFront_Comparison_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"compares"}
{"type":"relation","from":"DomRF_KeyAndLegal_Apr26","to":"DomRF_API_KnObject_Apr26","relationType":"applies_to"}
{"type":"relation","from":"DomRF_KeyAndLegal_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"applies_to"}
{"type":"relation","from":"DomRF_KeyAndLegal_Apr26","to":"DomRF_API_KnDicts_Apr26","relationType":"applies_to"}
{"type":"relation","from":"DomRF_Integration_Docs_Apr26","to":"DomRF_OfficialAuth_Apr26","relationType":"describes"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab8_Quartirografia_Apr26","relationType":"tile1_uses"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"tile2_uses"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab6_Realization_Apr26","relationType":"tile3_uses"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab7_ReadyConstruction_Apr26","relationType":"tile3_uses"}
{"type":"relation","from":"DomRF_Tab9_BuildingCommissioning_Apr26","to":"DomRF_Tab11_MortgageStats_Apr26","relationType":"shares_backend_with"}
{"type":"relation","from":"DomRF_Recon_AcceptVersionLeak_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_OIDC_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_Stack_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_RobotsTxt_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_OptionsPost_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_CORS_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_PortalSitemap_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_NoSourceMaps_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_DisclosurePlan_Apr26","to":"DomRF_Recon_Summary_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DomRF_Recon_AcceptVersionLeak_Apr26","to":"DomRF_Host_Apr26","relationType":"annotates"}
{"type":"relation","from":"DomRF_Recon_AcceptVersionLeak_Apr26","to":"DomRF_Recon_Stack_Apr26","relationType":"evidence_for"}
{"type":"relation","from":"DomRF_Recon_OIDC_Apr26","to":"DomRF_OfficialAuth_Apr26","relationType":"extends"}
{"type":"relation","from":"DomRF_Recon_OIDC_Apr26","to":"DomRF_Recon_Stack_Apr26","relationType":"evidence_for"}
{"type":"relation","from":"DomRF_Recon_RobotsTxt_Apr26","to":"DomRF_Enums_Apr26","relationType":"complements"}
{"type":"relation","from":"DomRF_Recon_RobotsTxt_Apr26","to":"DomRF_Recon_PortalSitemap_Apr26","relationType":"leads_to"}
{"type":"relation","from":"DomRF_Recon_OptionsPost_Apr26","to":"DomRF_API_KnObject_Apr26","relationType":"annotates"}
{"type":"relation","from":"DomRF_Recon_CORS_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"annotates"}
{"type":"relation","from":"DomRF_Recon_CORS_Apr26","to":"DomRF_API_KnObject_Apr26","relationType":"annotates"}
{"type":"relation","from":"DomRF_Recon_PortalSitemap_Apr26","to":"DomRF_API_Registries_Apr26","relationType":"complements"}
{"type":"relation","from":"DomRF_Recon_PortalSitemap_Apr26","to":"DomRF_ExtractFlow_Objects_Apr26","relationType":"alternative_to"}
{"type":"relation","from":"DomRF_Recon_DisclosurePlan_Apr26","to":"DomRF_Recon_AcceptVersionLeak_Apr26","relationType":"targets"}
{"type":"relation","from":"DomRF_Recon_DisclosurePlan_Apr26","to":"DomRF_Recon_OIDC_Apr26","relationType":"targets"}
{"type":"relation","from":"DomRF_Recon_Stack_Apr26","to":"DomRF_Architecture_Apr26","relationType":"annotates"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"is_aggregate_for"}
{"type":"relation","from":"DataSource_Fedstat_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"is_aggregate_for"}
{"type":"relation","from":"DataSource_Rosreestr_OpenService_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"is_aggregate_for"}
{"type":"relation","from":"DataSource_UPN_Ekb_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"is_aggregate_for"}
{"type":"relation","from":"DataSource_DomRFAsPerDeal_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"best_synthetic_approximation_for"}
{"type":"relation","from":"DataSource_DomRFAsPerDeal_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"uses"}
{"type":"relation","from":"DataSource_DomRFAsPerDeal_Apr26","to":"DomRF_PerFlat_ETL_Apr26","relationType":"implements"}
{"type":"relation","from":"DataSource_DomRFAsPerDeal_Apr26","to":"DomRF_PerFlat_VelocityTracker_Apr26","relationType":"extends"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"DomRF_Tab10_MortgageRates_Apr26","relationType":"complements"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"DomRF_Tab11_MortgageStats_Apr26","relationType":"complements"}
{"type":"relation","from":"DataSource_Fedstat_Apr26","to":"DomRF_Tab1_HousingIndicators_Apr26","relationType":"cross_validates"}
{"type":"relation","from":"DataSource_UPN_Ekb_Apr26","to":"DomRF_API_KnFlats_Apr26","relationType":"regional_complement_for"}
{"type":"relation","from":"DataSource_Rosreestr_OpenService_Apr26","to":"DataSource_Fedstat_Apr26","relationType":"publishes_aggregates_via"}
{"type":"relation","from":"DataSource_PerDeal_Reality_Apr26","to":"DomRF_PlanA_Mapping_Apr26","relationType":"informs"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Apr26","to":"DataSource_Rosreestr_OpenService_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Schema_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"describes_schema_of"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"validates"}
{"type":"relation","from":"DataSource_Rosreestr_ETL_Plan_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"implements"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Limits_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"qualifies"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"primary_solution_for"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Apr26","to":"DataSource_DomRFAsPerDeal_Apr26","relationType":"supersedes_for_per_deal"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Apr26","to":"DomRF_PlanA_Mapping_Apr26","relationType":"tile2_primary"}
{"type":"relation","from":"DataSource_Rosreestr_ETL_Plan_Apr26","to":"DomRF_PerFlat_ETL_Apr26","relationType":"complements"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026","to":"DataSource_UPN_Ekb_Apr26","relationType":"ground_truth_for"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026","to":"DataSource_Fedstat_Apr26","relationType":"ground_truth_for"}
{"type":"relation","from":"NSPD_OAuth_Architecture_Apr26","to":"NSPD_Architecture_Apr26","relationType":"extends"}
{"type":"relation","from":"NSPD_PhysicAccess_Apr26","to":"NSPD_OAuth_Architecture_Apr26","relationType":"uses"}
{"type":"relation","from":"NSPD_MarketAnalytics_API_Apr26","to":"NSPD_PhysicAccess_Apr26","relationType":"accessible_via"}
{"type":"relation","from":"NSPD_MarketAnalytics_API_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"based_on_same_source"}
{"type":"relation","from":"NSPD_AEGGIS_WMTS_Apr26","to":"NSPD_Architecture_Apr26","relationType":"extends"}
{"type":"relation","from":"NSPD_PII_Leak_Apr26","to":"NSPD_OAuth_Architecture_Apr26","relationType":"qualifies"}
{"type":"relation","from":"NSPD_PII_Leak_Apr26","to":"Rosreestr_Recon_Findings_Apr26","relationType":"complements"}
{"type":"relation","from":"NSPD_MarketAnalytics_API_Apr26","to":"DomRF_PlanA_Mapping_Apr26","relationType":"tile2_alternative"}
{"type":"relation","from":"NSPD_PhysicAccess_Apr26","to":"Rosreestr_SiteMap_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"NSPD_MarketAnalytics_FullArchitecture_Apr26","to":"NSPD_MarketAnalytics_API_Apr26","relationType":"supersedes"}
{"type":"relation","from":"NSPD_MarketAnalytics_FullArchitecture_Apr26","to":"NSPD_OAuth_Architecture_Apr26","relationType":"uses_auth_from"}
{"type":"relation","from":"NSPD_MarketAnalytics_FullArchitecture_Apr26","to":"NSPD_PhysicAccess_Apr26","relationType":"tested_with"}
{"type":"relation","from":"NSPD_OrgOnly_Endpoints_Apr26","to":"NSPD_MarketAnalytics_FullArchitecture_Apr26","relationType":"qualifies"}
{"type":"relation","from":"NSPD_OrgOnly_Endpoints_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"duplicates_data_of"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"NSPD_MarketAnalytics_FullArchitecture_Apr26","relationType":"applies"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"DomRF_PlanA_Mapping_Apr26","relationType":"tile2_alternative_to"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"Stages_MVP_v1","relationType":"extends_stage_2a_for"}
{"type":"relation","from":"TechStack_v2.2","to":"Project_GenDesign","relationType":"defines_tech_stack_for"}
{"type":"relation","from":"Stages_MVP_v1","to":"Project_GenDesign","relationType":"defines_roadmap_for"}
{"type":"relation","from":"Team_Setup","to":"Project_GenDesign","relationType":"executes"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"Project_GenDesign","relationType":"pivot_decision_for"}
{"type":"relation","from":"WorkSplit_Generative_Stage1","to":"Stages_MVP_v1","relationType":"details_phase_of"}
{"type":"relation","from":"WorkSplit_Generative_Stage1","to":"Team_Setup","relationType":"assigns_work_in"}
{"type":"relation","from":"Hosting_Decision_Apr25","to":"Project_GenDesign","relationType":"hosting_choice_for"}
{"type":"relation","from":"Hosting_Decision_Apr25","to":"Hosting_Pricing_Apr25","relationType":"informed_by"}
{"type":"relation","from":"Runbook_VPS_Setup_Beget","to":"Hosting_Pricing_Apr25","relationType":"implements_choice_from"}
{"type":"relation","from":"Runbook_VPS_Setup_Beget","to":"Project_GenDesign","relationType":"production_runbook_for"}
{"type":"relation","from":"Sentry_Setup_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"deployed_on_top_of"}
{"type":"relation","from":"OpsBundle_Apr26","to":"DockerOps_Apr26","relationType":"follows"}
{"type":"relation","from":"OpsBundle_Apr26","to":"Production_Wipe_Apr26","relationType":"will_apply_after"}
{"type":"relation","from":"Production_Wipe_Apr26","to":"DockerOps_Apr26","relationType":"applied_changes_from"}
{"type":"relation","from":"DockerOps_Apr26","to":"Sentry_Setup_Apr26","relationType":"precedes"}
{"type":"relation","from":"DomRF_Tab2_LaunchAndCommissioning_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab4_DevelopersDashboard_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab7_ReadyConstruction_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab8_Quartirografia_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab9_BuildingCommissioning_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_Tab11_MortgageStats_Apr26","to":"DomRF_Architecture_Apr26","relationType":"follows"}
{"type":"relation","from":"DomRF_API_PortalAnalytics_Apr26","to":"DomRF_Architecture_Apr26","relationType":"implements_group_a_of"}
{"type":"relation","from":"DomRF_Enums_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"provides_enums_for"}
{"type":"relation","from":"DomRF_KeyAndLegal_Apr26","to":"DomRF_Architecture_Apr26","relationType":"documents_legal_status_of"}
{"type":"relation","from":"DomRF_KeyAndLegal_Apr26","to":"DomRF_Host_Apr26","relationType":"qualifies_auth_on"}
{"type":"relation","from":"DomRF_OfficialVsFront_Comparison_Apr26","to":"DomRF_Architecture_Apr26","relationType":"compares_against_official"}
{"type":"relation","from":"DomRF_OfficialVsFront_Comparison_Apr26","to":"DomRF_Spec_APF_v22","relationType":"compares"}
{"type":"relation","from":"DomRF_Recon_OptionsPost_Apr26","to":"DomRF_Architecture_Apr26","relationType":"annotates"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Architecture_Apr26","relationType":"uses"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab1_HousingIndicators_Apr26","relationType":"additional_source"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab2_LaunchAndCommissioning_Apr26","relationType":"additional_source"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab3_ProjectFinance_Apr26","relationType":"additional_source"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_Tab5_Escrow_Apr26","relationType":"additional_source"}
{"type":"relation","from":"DomRF_PlanA_Mapping_Apr26","to":"DomRF_KeyAndLegal_Apr26","relationType":"tile2_uses_auth_from"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"DomRF_PlanA_Mapping_Apr26","relationType":"tile_design_described_in"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"now_primary_data_source"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"DataSources_Analysis_Apr26","relationType":"data_layer_designed_in"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"Stages_MVP_v1","relationType":"modifies"}
{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Stages_MVP_v1","relationType":"was_planned_for_stage_2a"}
{"type":"relation","from":"SalesTracking_Strategy_Apr25","to":"Project_GenDesign","relationType":"data_moat_for"}
{"type":"relation","from":"DataSources_Pricing_Apr25","to":"Project_GenDesign","relationType":"early_research_for"}
{"type":"relation","from":"DataSource_PerDeal_Reality_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"unblocks_tile2_of"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Apr26","to":"Project_GenDesign","relationType":"primary_pricing_source_for"}
{"type":"relation","from":"DataSource_Rosreestr_DealsCSV_Apr26","to":"DomRF_PlanA_Mapping_Apr26","relationType":"tile2_primary_alternative_to"}
{"type":"relation","from":"DataSource_Rosreestr_ETL_Plan_Apr26","to":"Stages_MVP_v1","relationType":"details_stage_2a_etl_for"}
{"type":"relation","from":"DataSource_UPN_Ekb_Apr26","to":"Project_GenDesign","relationType":"ekb_baseline_for"}
{"type":"relation","from":"Rosreestr_SiteMap_Apr26","to":"DataSource_Rosreestr_OpenService_Apr26","relationType":"lists"}
{"type":"relation","from":"Rosreestr_SiteMap_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"lists"}
{"type":"relation","from":"Rosreestr_SiteMap_Apr26","to":"Rosreestr_OpenData_17Sets_Apr26","relationType":"lists"}
{"type":"relation","from":"Rosreestr_SiteMap_Apr26","to":"NSPD_Architecture_Apr26","relationType":"lists"}
{"type":"relation","from":"Rosreestr_OpenData_17Sets_Apr26","to":"Rosreestr_SiteMap_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"Rosreestr_Recon_Findings_Apr26","to":"Rosreestr_SiteMap_Apr26","relationType":"security_annotation_for"}
{"type":"relation","from":"Rosreestr_Recon_Findings_Apr26","to":"NSPD_Architecture_Apr26","relationType":"annotates"}
{"type":"relation","from":"Rosreestr_TLS_Note_Apr26","to":"DataSource_Rosreestr_ETL_Plan_Apr26","relationType":"affects"}
{"type":"relation","from":"Rosreestr_TLS_Note_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"affects_download_of"}
{"type":"relation","from":"NSPD_Architecture_Apr26","to":"Rosreestr_SiteMap_Apr26","relationType":"is_part_of"}
{"type":"relation","from":"NSPD_OAuth_Architecture_Apr26","to":"NSPD_Architecture_Apr26","relationType":"auth_subsystem_of"}
{"type":"relation","from":"NSPD_PhysicAccess_Apr26","to":"NSPD_Architecture_Apr26","relationType":"tested_role_in"}
{"type":"relation","from":"NSPD_AEGGIS_WMTS_Apr26","to":"NSPD_Architecture_Apr26","relationType":"is_subsystem_of"}
{"type":"relation","from":"NSPD_AEGGIS_WMTS_Apr26","to":"NSPD_MarketAnalytics_FullArchitecture_Apr26","relationType":"provides_basemap_for"}
{"type":"relation","from":"NSPD_AEGGIS_WMTS_Apr26","to":"Project_GenDesign","relationType":"embeddable_basemap_for"}
{"type":"relation","from":"NSPD_PII_Leak_Apr26","to":"NSPD_OAuth_Architecture_Apr26","relationType":"security_annotation_for"}
{"type":"relation","from":"NSPD_PII_Leak_Apr26","to":"NSPD_PhysicAccess_Apr26","relationType":"annotates"}
{"type":"relation","from":"NSPD_MarketAnalytics_API_Apr26","to":"NSPD_Architecture_Apr26","relationType":"is_subsystem_of"}
{"type":"relation","from":"NSPD_MarketAnalytics_FullArchitecture_Apr26","to":"NSPD_Architecture_Apr26","relationType":"is_subsystem_of"}
{"type":"relation","from":"NSPD_MarketAnalytics_FullArchitecture_Apr26","to":"Project_GenDesign","relationType":"potential_data_source_for"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"Project_GenDesign","relationType":"data_value_assessment_for"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"informs_tile2_of"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"cross_validates_with"}
{"type":"relation","from":"NSPD_DataValue_For_GenDesign_Apr26","to":"NSPD_AEGGIS_WMTS_Apr26","relationType":"uses_basemap"}
{"type":"relation","from":"NSPD_OrgOnly_Endpoints_Apr26","to":"NSPD_PhysicAccess_Apr26","relationType":"qualifies_403_for"}
{"type":"relation","from":"DomRF_Recon_Stack_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"stack_annotation_for"}
{"type":"relation","from":"NorthStar_DiscoveryMVP","to":"Project_GenDesign","relationType":"goal_for"}
{"type":"relation","from":"Stages_MVP_v1","to":"NorthStar_DiscoveryMVP","relationType":"delivers_toward"}
{"type":"relation","from":"PlanA_AnalyticsFirst_Apr25","to":"NorthStar_DiscoveryMVP","relationType":"alternative_path_to"}
{"type":"relation","from":"Validation_Findings_Apr25","to":"Project_GenDesign","relationType":"validates_business_plan_for"}
{"type":"relation","from":"Validation_Findings_Apr25","to":"TechStack_v2.2","relationType":"flagged_drift_against"}
{"type":"relation","from":"Validation_Findings_Apr25","to":"NorthStar_DiscoveryMVP","relationType":"calibrates_kpi_of"}
{"type":"relation","from":"Validation_Findings_Apr25","to":"Stages_MVP_v1","relationType":"informed_scope_of"}
{"type":"relation","from":"Domain_Setup_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"configures_domain_for"}
{"type":"relation","from":"Domain_Setup_Apr26","to":"Project_GenDesign","relationType":"domain_for"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"milestone_of"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"DockerOps_Apr26","relationType":"completed_after"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"Project_GenDesign","relationType":"production_milestone_for"}
{"type":"relation","from":"HTTPS_Live_Apr26","to":"NorthStar_DiscoveryMVP","relationType":"infra_acceptance_for"}
{"type":"relation","from":"DataSource_Fedstat_Apr26","to":"Project_GenDesign","relationType":"baseline_pricing_for"}
{"type":"relation","from":"DataSource_Fedstat_Apr26","to":"DataSources_Analysis_Apr26","relationType":"described_in"}
{"type":"relation","from":"DataSource_Fedstat_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"cross_validates_with"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"Project_GenDesign","relationType":"mortgage_data_for"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"DataSource_PerDeal_Reality_Apr26","relationType":"cross_validation_for"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"DomRF_Tab11_MortgageStats_Apr26","relationType":"complements_supply_side_of"}
{"type":"relation","from":"DataSource_CBR_Mortgage_Apr26","to":"DataSources_Analysis_Apr26","relationType":"described_in"}
{"type":"relation","from":"DomRF_Recon_RobotsTxt_Apr26","to":"DomRF_Architecture_Apr26","relationType":"annotates"}
{"type":"relation","from":"DomRF_Recon_RobotsTxt_Apr26","to":"DomRF_Enums_Apr26","relationType":"expands_param_list_for"}
{"type":"relation","from":"DomRF_Integration_Docs_Apr26","to":"DomRF_OfficialVsFront_Comparison_Apr26","relationType":"supports_comparison"}
{"type":"relation","from":"DomRF_Integration_Docs_Apr26","to":"DomRF_Spec_APF_v22","relationType":"documents"}
{"type":"relation","from":"DomRF_Integration_Docs_Apr26","to":"DomRF_Spec_SJS_v130","relationType":"documents"}
{"type":"relation","from":"DomRF_Integration_Docs_Apr26","to":"DomRF_Spec_NSI_v101","relationType":"documents"}
{"type":"relation","from":"DomRF_Integration_Docs_Apr26","to":"DomRF_Spec_UOPO_v102","relationType":"documents"}
{"type":"relation","from":"DomRF_OfficialAuth_Apr26","to":"DomRF_Architecture_Apr26","relationType":"official_b2b_auth_for"}
{"type":"relation","from":"DomRF_Spec_SJS_v130","to":"DomRF_OfficialVsFront_Comparison_Apr26","relationType":"compared_in"}
{"type":"relation","from":"DomRF_Spec_NSI_v101","to":"DomRF_OfficialVsFront_Comparison_Apr26","relationType":"compared_in"}
{"type":"relation","from":"DomRF_Spec_UOPO_v102","to":"DomRF_OfficialVsFront_Comparison_Apr26","relationType":"compared_in"}
{"type":"relation","from":"DomRF_Spec_APF_v22","to":"DomRF_OfficialVsFront_Comparison_Apr26","relationType":"compared_in"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"DomRF_PlanA_Mapping_Apr26","relationType":"concretized_into"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"describes_priority_1"}
{"type":"relation","from":"DataSources_Analysis_Apr26","to":"DataSource_UPN_Ekb_Apr26","relationType":"lists_as_ekb_baseline"}
{"type":"relation","from":"Sentry_Setup_Apr26","to":"Project_GenDesign","relationType":"observability_for"}
{"type":"relation","from":"OpsBundle_Apr26","to":"Stages_MVP_v1","relationType":"prepares_alembic_for_stage_2a"}
{"type":"relation","from":"Domclick_DDF_Report_Nov2025","to":"Project_GenDesign","relationType":"industry_intelligence_for"}
{"type":"relation","from":"Domclick_DDF_Report_Nov2025","to":"DataSources_Analysis_Apr26","relationType":"extends"}
{"type":"relation","from":"Domclick_DDF_Report_Nov2025","to":"PlanA_AnalyticsFirst_Apr25","relationType":"validates_3_tile_thesis_for"}
{"type":"relation","from":"Affordability_Trends_DDF_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"Affordability_Trends_DDF_Nov2025","to":"PlanA_AnalyticsFirst_Apr25","relationType":"informs_tile2_of"}
{"type":"relation","from":"Affordability_Trends_DDF_Nov2025","to":"DataSource_CBR_Mortgage_Apr26","relationType":"complements"}
{"type":"relation","from":"PriceGap_Quality_vs_Rate_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"PriceGap_Quality_vs_Rate_Nov2025","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"explains_dkp_ddu_gap_in"}
{"type":"relation","from":"PriceGap_Quality_vs_Rate_Nov2025","to":"Sverdlovsk_Profile_DDF_Nov2025","relationType":"highlights_sverdlovsk_in"}
{"type":"relation","from":"AlternativeDeal_Trends_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"AlternativeDeal_Trends_Nov2025","to":"PlanA_AnalyticsFirst_Apr25","relationType":"informs_tile2_of"}
{"type":"relation","from":"AlternativeDeal_Trends_Nov2025","to":"Sverdlovsk_Profile_DDF_Nov2025","relationType":"evaluates"}
{"type":"relation","from":"RepeatedMortgage_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"RepeatedMortgage_Nov2025","to":"PlanA_AnalyticsFirst_Apr25","relationType":"informs_tile1_of"}
{"type":"relation","from":"RepeatedMortgage_Nov2025","to":"QualityShift_NewBuild_2021_2025","relationType":"explains_driver_of"}
{"type":"relation","from":"QualityShift_NewBuild_2021_2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"QualityShift_NewBuild_2021_2025","to":"PlanA_AnalyticsFirst_Apr25","relationType":"redefines_tile1_for"}
{"type":"relation","from":"QualityShift_NewBuild_2021_2025","to":"DomRF_Tab8_Quartirografia_Apr26","relationType":"trend_signal_for"}
{"type":"relation","from":"QualityShift_NewBuild_2021_2025","to":"Stages_MVP_v1","relationType":"informs_unit_mix_defaults_for"}
{"type":"relation","from":"RegionGroups_BuildingDemand_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"RegionGroups_BuildingDemand_Nov2025","to":"Sverdlovsk_Profile_DDF_Nov2025","relationType":"classifies"}
{"type":"relation","from":"RegionGroups_BuildingDemand_Nov2025","to":"Project_GenDesign","relationType":"expansion_strategy_for"}
{"type":"relation","from":"DemandIndex_Domclick_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"DemandIndex_Domclick_Nov2025","to":"Project_GenDesign","relationType":"site_finder_blueprint_for"}
{"type":"relation","from":"DemandIndex_Domclick_Nov2025","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"uses_factor_from"}
{"type":"relation","from":"DemandIndex_Domclick_Nov2025","to":"DomRF_Tab7_ReadyConstruction_Apr26","relationType":"uses_velocity_from"}
{"type":"relation","from":"DemandIndex_Domclick_Nov2025","to":"Stages_MVP_v1","relationType":"informs_site_finder_scoring_for"}
{"type":"relation","from":"Regional_Migration_Buyers_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"Regional_Migration_Buyers_Nov2025","to":"Sverdlovsk_Profile_DDF_Nov2025","relationType":"places"}
{"type":"relation","from":"Regional_Migration_Buyers_Nov2025","to":"PlanA_AnalyticsFirst_Apr25","relationType":"adds_buyer_origin_factor_to"}
{"type":"relation","from":"Sverdlovsk_Profile_DDF_Nov2025","to":"Domclick_DDF_Report_Nov2025","relationType":"is_section_of"}
{"type":"relation","from":"Sverdlovsk_Profile_DDF_Nov2025","to":"Project_GenDesign","relationType":"regional_market_profile_for"}
{"type":"relation","from":"Sverdlovsk_Profile_DDF_Nov2025","to":"DataSource_UPN_Ekb_Apr26","relationType":"complements"}
{"type":"relation","from":"Sverdlovsk_Profile_DDF_Nov2025","to":"DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026","relationType":"context_for"}
{"type":"relation","from":"Domclick_DDF_Report_Nov2025","to":"DataSource_Fedstat_Apr26","relationType":"uses_rosstat_data_via"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"DataSource_Rosreestr_DealsCSV_Apr26","relationType":"implements_etl_for"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"DataSource_Rosreestr_ETL_Plan_Apr26","relationType":"executes"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"Project_GenDesign","relationType":"data_layer_milestone_for"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"deployed_on"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"unblocks_tile2_for"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"Stages_MVP_v1","relationType":"advances_stage_2a_data_layer_of"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"DataSource_Rosreestr_DealsCSV_Sverdl_Q1_2026","relationType":"validated_against"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"Domclick_DDF_Report_Nov2025","relationType":"cross_validated_with"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"PriceGap_Quality_vs_Rate_Nov2025","relationType":"confirms_with_real_deals"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"DataSource_Rosreestr_DealsCSV_Limits_Apr26","relationType":"encountered_issues_described_in"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"DataSource_Rosreestr_DealsCSV_Schema_Apr26","relationType":"applied_schema_from"}
{"type":"relation","from":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","to":"Rosreestr_TLS_Note_Apr26","relationType":"used_workaround_from"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"DomRF_Architecture_Apr26","relationType":"implements_etl_for"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"DomRF_API_PortalAnalytics_Apr26","relationType":"executes"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"Project_GenDesign","relationType":"data_layer_milestone_for"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"deployed_on"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"unblocks_tile1_for"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","relationType":"complements_pricing_with_quartirografia"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"DataSources_Analysis_Apr26","relationType":"validates_priority1_choice_of"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"QualityShift_NewBuild_2021_2025","relationType":"snapshot_confirms_trend_of"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"DomRF_Tab8_Quartirografia_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_Analytics_Loaded_Prod_Apr26","to":"DomRF_KeyAndLegal_Apr26","relationType":"operates_under_legal_terms_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DomRF_Analytics_Loaded_Prod_Apr26","relationType":"extends_with_xlsx_pdf"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"Project_GenDesign","relationType":"data_layer_milestone_for"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"deployed_on"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"unblocks_tile3_for"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DomRF_Tab7_ReadyConstruction_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DomRF_Tab5_Escrow_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DomRF_Tab11_MortgageStats_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DomRF_Tab9_BuildingCommissioning_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DomRF_Tab2_LaunchAndCommissioning_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","relationType":"complements_with_supply_side"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"Domclick_DDF_Report_Nov2025","relationType":"confirms_industry_thesis_of"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"DataSource_CBR_Mortgage_Apr26","relationType":"complements_with_bank_rates"}
{"type":"relation","from":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","to":"Sverdlovsk_Profile_DDF_Nov2025","relationType":"validates_with_real_market_data"}
{"type":"relation","from":"DomRF_Playwright_Scraper_Apr26","to":"Project_GenDesign","relationType":"production_etl_for"}
{"type":"relation","from":"DomRF_Playwright_Scraper_Apr26","to":"DomRF_Architecture_Apr26","relationType":"automates_scraping_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Playwright_Scraper_Apr26","relationType":"uses_output_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"Runbook_VPS_Setup_Beget","relationType":"deployed_on"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Tab2_LaunchAndCommissioning_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Tab7_ReadyConstruction_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Tab3_ProjectFinance_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Tab9_BuildingCommissioning_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Tab11_MortgageStats_Apr26","relationType":"concrete_implementation_of"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_Analytics_Loaded_Prod_Apr26","relationType":"extends_with_normalized_endpoints"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","relationType":"extends_with_full_api_data"}
{"type":"relation","from":"DomRF_Scraped_Loaded_Prod_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"unblocks_full_data_layer_for"}
{"type":"relation","from":"DomRF_Schema_Relations_Apr26","to":"Project_GenDesign","relationType":"data_layer_integration_for"}
{"type":"relation","from":"DomRF_Schema_Relations_Apr26","to":"DomRF_Scraped_Loaded_Prod_Apr26","relationType":"links_tables_of"}
{"type":"relation","from":"DomRF_Schema_Relations_Apr26","to":"DomRF_Analytics_Loaded_Prod_Apr26","relationType":"links_tables_of"}
{"type":"relation","from":"DomRF_Schema_Relations_Apr26","to":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","relationType":"links_tables_of"}
{"type":"relation","from":"DomRF_Schema_Relations_Apr26","to":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","relationType":"joins_pricing_with_quartirografia_via_view"}
{"type":"relation","from":"DomRF_Schema_Relations_Apr26","to":"PlanA_AnalyticsFirst_Apr25","relationType":"enables_unified_query_for"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"Project_GenDesign","relationType":"session_summary_for"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"Rosreestr_DealsCSV_Loaded_Prod_Apr26","relationType":"completed_milestone"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"DomRF_Analytics_Loaded_Prod_Apr26","relationType":"completed_milestone"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","relationType":"completed_milestone"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"DomRF_Scraped_Loaded_Prod_Apr26","relationType":"completed_milestone"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"DomRF_Schema_Relations_Apr26","relationType":"completed_milestone"}
{"type":"relation","from":"DomRF_History_Loaded_Apr27_2026","to":"DomRF_Tab6_Realization_Apr26","relationType":"verifies_historical_support_of"}
{"type":"relation","from":"DomRF_History_Loaded_Apr27_2026","to":"DomRF_Tab7_ReadyConstruction_Apr26","relationType":"verifies_historical_support_of"}
{"type":"relation","from":"Sverdl_Quartirography_Report_Apr27","to":"DomRF_History_Loaded_Apr27_2026","relationType":"uses_data_from"}
{"type":"relation","from":"PRINZIP_Strategy_Apr27","to":"Sverdl_Quartirography_Report_Apr27","relationType":"derived_from"}
{"type":"relation","from":"Schema_Tables_Map_Apr27","to":"Schema_FK_Map_Apr27","relationType":"complements"}
{"type":"relation","from":"Schema_Tables_Map_Apr27","to":"Schema_Views_Catalogue_Apr27","relationType":"queried_via"}
{"type":"relation","from":"Schema_FK_Map_Apr27","to":"Schema_Tables_Map_Apr27","relationType":"constrains"}
{"type":"relation","from":"Schema_Views_Catalogue_Apr27","to":"Schema_Tables_Map_Apr27","relationType":"abstracts"}
{"type":"relation","from":"Schema_ETL_Artefacts_Apr27","to":"Schema_Tables_Map_Apr27","relationType":"produces"}
{"type":"relation","from":"Schema_ETL_Artefacts_Apr27","to":"Schema_FK_Map_Apr27","relationType":"produces"}
{"type":"relation","from":"Schema_ETL_Artefacts_Apr27","to":"Schema_Views_Catalogue_Apr27","relationType":"produces"}
{"type":"relation","from":"Schema_Open_TODOs_Apr27","to":"Schema_Tables_Map_Apr27","relationType":"extends_planned"}
{"type":"relation","from":"DomRF_History_Loaded_Apr27_2026","to":"Schema_ETL_Artefacts_Apr27","relationType":"documented_in"}
{"type":"relation","from":"Sverdl_Market_Trend_Apr27","to":"DomRF_History_Loaded_Apr27_2026","relationType":"uses_data_from"}
{"type":"relation","from":"Sverdl_Market_Trend_Apr27","to":"Schema_Tables_Map_Apr27","relationType":"queries"}
{"type":"relation","from":"Sverdl_Market_Trend_Apr27","to":"Sverdl_Quartirography_Report_Apr27","relationType":"summarized_in"}
{"type":"relation","from":"Competitor_Benchmark_Brusnika_Apr27","to":"Schema_Views_Catalogue_Apr27","relationType":"uses_view"}
{"type":"relation","from":"Competitor_Benchmark_Brusnika_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"informs"}
{"type":"relation","from":"Competitor_Benchmark_ForumGroup_Apr27","to":"Schema_Views_Catalogue_Apr27","relationType":"uses_view"}
{"type":"relation","from":"Competitor_Benchmark_ForumGroup_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"informs"}
{"type":"relation","from":"Competitor_Benchmark_Brusnika_Apr27","to":"Competitor_Benchmark_ForumGroup_Apr27","relationType":"compared_with"}
{"type":"relation","from":"PRINZIP_Strategy_Apr27","to":"Sverdl_Market_Trend_Apr27","relationType":"contextualized_by"}
{"type":"relation","from":"Sverdl_Quartirography_Report_Apr27","to":"Schema_Views_Catalogue_Apr27","relationType":"queried_via"}
{"type":"relation","from":"Schema_Open_TODOs_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"blocks_completion_of"}
{"type":"relation","from":"Schema_Views_Catalogue_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"enables_analysis_for"}
{"type":"relation","from":"Schema_Views_Catalogue_Apr27","to":"Sverdl_Quartirography_Report_Apr27","relationType":"enables_analysis_for"}
{"type":"relation","from":"Session_End_Apr26_2026","to":"Schema_Tables_Map_Apr27","relationType":"predates_state_of"}
{"type":"relation","from":"DomRF_History_Loaded_Apr27_2026","to":"Schema_Tables_Map_Apr27","relationType":"extends_data_in"}
{"type":"relation","from":"PRINZIP_Strategy_Apr27","to":"Schema_Views_Catalogue_Apr27","relationType":"queries"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"DomRF_Playwright_Scraper_Apr26","relationType":"extends"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"Schema_Tables_Map_Apr27","relationType":"adds_tables_to"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"DomRF_Tab1_HousingIndicators_Apr26","relationType":"implements_spec_from"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"DomRF_Tab6_Realization_Apr26","relationType":"implements_spec_from"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"DomRF_Tab12_StatRows_Apr26","relationType":"implements_spec_from"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"DomRF_Scraped_Loaded_Prod_Apr26","relationType":"completes_remaining_5_pages_of"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"DomRF_XLSX_PDF_Snapshot_Loaded_Apr26","relationType":"extends_with_full_region_coverage"}
{"type":"relation","from":"DomRF_Lazy_Loaded_Apr27_2026","to":"Schema_ETL_Artefacts_Apr27","relationType":"documented_in"}
{"type":"relation","from":"DomRF_History_Loaded_Apr27_2026","to":"DomRF_Lazy_Loaded_Apr27_2026","relationType":"extends_with_historical_data"}
{"type":"relation","from":"Anton_Imported_Apr27_2026","to":"Schema_Tables_Map_Apr27","relationType":"extends_data_in"}
{"type":"relation","from":"Anton_Imported_Apr27_2026","to":"Schema_ETL_Artefacts_Apr27","relationType":"documented_in"}
{"type":"relation","from":"Anton_Imported_Apr27_2026","to":"DomRF_History_Loaded_Apr27_2026","relationType":"complements_history_with_breadth"}
{"type":"relation","from":"PRINZIP_Strategy_Apr27","to":"Anton_Imported_Apr27_2026","relationType":"uses_data_from"}
{"type":"relation","from":"Sverdl_Quartirography_Report_Apr27","to":"Anton_Imported_Apr27_2026","relationType":"uses_data_from"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"Session_End_Apr26_2026","relationType":"succeeds"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"Schema_Tables_Map_Apr27","relationType":"summarizes_state_of"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"Schema_Open_TODOs_Apr27","relationType":"points_to_next_actions"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"PRINZIP_Strategy_Apr27","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"Sverdl_Quartirography_Report_Apr27","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"DomRF_Lazy_Loaded_Apr27_2026","relationType":"completed_milestone"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"DomRF_History_Loaded_Apr27_2026","relationType":"completed_milestone"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"Anton_Imported_Apr27_2026","relationType":"completed_milestone"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"surfaces_in_ui"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"Sverdl_Quartirography_Report_Apr27","relationType":"surfaces_in_ui"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"Schema_Open_TODOs_Apr27","relationType":"partially_resolves"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"Schema_Tables_Map_Apr27","relationType":"consumes_schema_from"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"Analytics_Dashboard_Apr27","relationType":"spawned_followup"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"Schema_Open_TODOs_Apr27","relationType":"resolves_todo_1"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"unblocks_analysis"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"Analytics_Dashboard_Apr27","relationType":"feeds_data_to"}
{"type":"relation","from":"Session_End_Apr27_2026","to":"DomRf_Kn_Scraper_Apr27","relationType":"spawned_followup"}
{"type":"relation","from":"Prinzip_CRM_Pipeline_Apr27","to":"DomRf_Kn_Scraper_Apr27","relationType":"complements_data_layer"}
{"type":"relation","from":"Prinzip_CRM_Pipeline_Apr27","to":"PRINZIP_Strategy_Apr27","relationType":"unblocks_conversion_analysis"}
{"type":"relation","from":"Route_Home","to":"Route_Analytics_Sverdl","relationType":"links_to"}
{"type":"relation","from":"Route_Home","to":"Route_Analytics_Prinzip","relationType":"links_to"}
{"type":"relation","from":"Route_Home","to":"Route_Analytics_Developers","relationType":"links_to"}
{"type":"relation","from":"Route_Home","to":"Route_Analytics_Object","relationType":"links_to"}
{"type":"relation","from":"Route_Home","to":"Route_Admin_Scrape","relationType":"links_to"}
{"type":"relation","from":"Route_Home","to":"Route_Admin_Leads","relationType":"links_to"}
{"type":"relation","from":"Route_Analytics_Prinzip","to":"Route_Analytics_Object","relationType":"drilldowns_into"}
{"type":"relation","from":"Route_Analytics_Developers","to":"Route_Analytics_Object","relationType":"drilldowns_into"}
{"type":"relation","from":"Route_Admin_Leads","to":"Route_Analytics_Object","relationType":"drilldowns_into"}
{"type":"relation","from":"Route_Analytics_Object","to":"Endpoint_Analytics_Object","relationType":"consumes"}
{"type":"relation","from":"Route_Analytics_Prinzip","to":"Endpoint_Analytics_Object","relationType":"consumes"}
{"type":"relation","from":"Route_Admin_Scrape","to":"Endpoint_Admin_Scrape","relationType":"consumes"}
{"type":"relation","from":"Route_Admin_Leads","to":"Endpoint_Admin_Leads","relationType":"consumes"}
{"type":"relation","from":"Route_Admin_Scrape","to":"Auth_Admin_Token","relationType":"protected_by"}
{"type":"relation","from":"Route_Admin_Leads","to":"Auth_Admin_Token","relationType":"protected_by"}
{"type":"relation","from":"Endpoint_Admin_Scrape","to":"Auth_Admin_Token","relationType":"validates"}
{"type":"relation","from":"Endpoint_Admin_Leads","to":"Auth_Admin_Token","relationType":"validates"}
{"type":"relation","from":"Endpoint_Admin_Scrape","to":"Module_Celery_App","relationType":"delegates_to"}
{"type":"relation","from":"Module_Celery_App","to":"Module_Scraper_Kn","relationType":"invokes"}
{"type":"relation","from":"Module_Scraper_Kn","to":"Module_Scraper_Stealth","relationType":"uses"}
{"type":"relation","from":"Module_Scraper_Stealth","to":"Stealth_Fingerprint_State","relationType":"loads"}
{"type":"relation","from":"Module_Scraper_Kn","to":"DomRf_Kn_Scraper_Apr27","relationType":"implements"}
{"type":"relation","from":"Endpoint_Admin_Leads","to":"PII_Compliance_152FZ","relationType":"enforces"}
{"type":"relation","from":"Prinzip_CRM_Pipeline_Apr27","to":"PII_Compliance_152FZ","relationType":"enforces"}
{"type":"relation","from":"Prinzip_CRM_Pipeline_Apr27","to":"Endpoint_Admin_Leads","relationType":"exposed_via"}
{"type":"relation","from":"Prinzip_CRM_Pipeline_Apr27","to":"Route_Admin_Leads","relationType":"rendered_in"}
{"type":"relation","from":"Docker_Multi_Target","to":"Module_Scraper_Stealth","relationType":"ships_chromium_for"}
{"type":"relation","from":"Docker_Multi_Target","to":"Module_Celery_App","relationType":"runs_worker_image"}
{"type":"relation","from":"Docker_Auto_Cleanup","to":"Docker_Multi_Target","relationType":"maintains"}
{"type":"relation","from":"GitHub_Issue_13_Closed","to":"Module_Scraper_Kn","relationType":"depends_on"}
{"type":"relation","from":"GitHub_Issue_14_Closed","to":"Prinzip_CRM_Pipeline_Apr27","relationType":"delivered_by"}
{"type":"relation","from":"GitHub_Issue_15_Closed","to":"Endpoint_Analytics_Object","relationType":"delivered_by"}
{"type":"relation","from":"GitHub_Issue_15_Closed","to":"Route_Analytics_Object","relationType":"delivered_by"}
{"type":"relation","from":"GitHub_Issue_16_Closed","to":"Docker_Multi_Target","relationType":"delivered_by"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"Route_Analytics_Sverdl","relationType":"rendered_as"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"Route_Analytics_Prinzip","relationType":"rendered_as"}
{"type":"relation","from":"Analytics_Dashboard_Apr27","to":"Route_Analytics_Developers","relationType":"rendered_as"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"Module_Scraper_Kn","relationType":"code_at"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"Module_Scraper_Stealth","relationType":"code_at"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"Module_Celery_App","relationType":"scheduled_via"}
{"type":"relation","from":"DomRf_Kn_Scraper_Apr27","to":"Stealth_Fingerprint_State","relationType":"uses_cookies_from"}
{"type":"relation","from":"Endpoint_Recommend_Mix","to":"Schema_Recommend_IO","relationType":"validates_with"}
{"type":"relation","from":"Endpoint_Recommend_Mix","to":"Module_Recommend_Query","relationType":"calls"}
{"type":"relation","from":"Module_Recommend_Query","to":"Module_Bucket_Distribution","relationType":"uses"}
{"type":"relation","from":"Module_Recommend_Query","to":"Window_Auto_Extend_24mo","relationType":"applies"}
{"type":"relation","from":"Module_Recommend_Query","to":"Class_Multiplier_Yandex","relationType":"applies"}
{"type":"relation","from":"Module_Bucket_Distribution","to":"Quartirography_Filter_Fix","relationType":"applies"}
{"type":"relation","from":"Module_Recommend_Query","to":"Limit_District_Median_Null","relationType":"limited_by"}
{"type":"relation","from":"Module_Recommend_Query","to":"Limit_District_Geometry","relationType":"limited_by"}
{"type":"relation","from":"Recommend_Level1_Apr27","to":"Endpoint_Recommend_Mix","relationType":"exposed_via"}
{"type":"relation","from":"Recommend_Level1_Apr27","to":"Module_Recommend_Query","relationType":"implemented_by"}
{"type":"relation","from":"Recommend_Level1_Apr27","to":"Route_Analytics_Recommend","relationType":"rendered_at"}
{"type":"relation","from":"Route_Analytics_Recommend","to":"Endpoint_Recommend_Mix","relationType":"consumes"}
{"type":"relation","from":"Route_Analytics_Recommend","to":"Component_Recommend_Form","relationType":"renders"}
{"type":"relation","from":"Route_Analytics_Recommend","to":"Component_Recommend_Sliders","relationType":"renders"}
{"type":"relation","from":"Route_Analytics_Recommend","to":"Component_Recommend_Charts","relationType":"renders"}
{"type":"relation","from":"Route_Analytics_Recommend","to":"Component_Recommend_Comparables","relationType":"renders"}
{"type":"relation","from":"Component_Recommend_Form","to":"Hook_useRecommendMix","relationType":"uses"}
{"type":"relation","from":"Hook_useRecommendMix","to":"Endpoint_Recommend_Mix","relationType":"calls"}
{"type":"relation","from":"Component_Recommend_Sliders","to":"Component_Recommend_Charts","relationType":"drives_recompute_of"}
{"type":"relation","from":"Component_Recommend_Comparables","to":"Route_Analytics_Object","relationType":"drilldowns_into"}
{"type":"relation","from":"Route_Home","to":"Route_Analytics_Recommend","relationType":"links_to"}
{"type":"relation","from":"Recommend_Level1_Apr27","to":"Schema_Open_TODOs_Apr27","relationType":"partially_resolves"}
{"type":"relation","from":"Endpoint_Photos_Serve","to":"Module_Photo_Thumbs","relationType":"uses"}
{"type":"relation","from":"Endpoint_Photos_Serve","to":"Photo_Lazy_Fetch","relationType":"applies"}
{"type":"relation","from":"Endpoint_Photos_Serve","to":"Schema_Photo_Thumb_Path","relationType":"reads_from"}
{"type":"relation","from":"Module_Photo_Thumbs","to":"Module_Scraper_Kn","relationType":"invoked_by"}
{"type":"relation","from":"Photo_Storage_Pipeline","to":"Endpoint_Photos_Serve","relationType":"exposed_via"}
{"type":"relation","from":"Photo_Storage_Pipeline","to":"Module_Photo_Thumbs","relationType":"uses"}
{"type":"relation","from":"Photo_Storage_Pipeline","to":"Schema_Photo_Thumb_Path","relationType":"requires"}
{"type":"relation","from":"Photo_Storage_Pipeline","to":"Photo_Lazy_Fetch","relationType":"uses"}
{"type":"relation","from":"Route_Analytics_Object","to":"Endpoint_Photos_Serve","relationType":"consumes"}
{"type":"relation","from":"Endpoint_Admin_Scrape","to":"Queue_Optimised_DB","relationType":"applies"}
{"type":"relation","from":"Endpoint_Admin_Scrape","to":"Zombie_Autocleanup","relationType":"applies"}
{"type":"relation","from":"Module_Celery_App","to":"Worker_Ready_Hook","relationType":"registers"}
{"type":"relation","from":"Module_Scraper_Kn","to":"Redis_Singleton_Lock","relationType":"uses"}
{"type":"relation","from":"Task_Resume_Kn_Run","to":"Redis_Singleton_Lock","relationType":"uses"}
{"type":"relation","from":"Task_Resume_Kn_Run","to":"Module_Scraper_Kn","relationType":"invokes"}
{"type":"relation","from":"Worker_Ready_Hook","to":"Task_Resume_Kn_Run","relationType":"enqueues"}
{"type":"relation","from":"Worker_Ready_Hook","to":"Schema_Resume_Columns","relationType":"reads_from"}
{"type":"relation","from":"Resume_Checkpoint_Mechanism","to":"Schema_Resume_Columns","relationType":"writes_to"}
{"type":"relation","from":"Resume_Checkpoint_Mechanism","to":"Worker_Ready_Hook","relationType":"triggered_by"}
{"type":"relation","from":"Resume_Checkpoint_Mechanism","to":"Task_Resume_Kn_Run","relationType":"executed_via"}
{"type":"relation","from":"Resume_Checkpoint_Mechanism","to":"Module_Scraper_Kn","relationType":"embedded_in"}
{"type":"relation","from":"Module_Scraper_Kn","to":"Module_Scrape_Log","relationType":"emits_via"}
{"type":"relation","from":"Module_Scrape_Log","to":"Schema_Scrape_Log_Table","relationType":"writes_to"}
{"type":"relation","from":"Endpoint_Scrape_Logs","to":"Schema_Scrape_Log_Table","relationType":"reads_from"}
{"type":"relation","from":"Endpoint_Scrape_Logs","to":"Auth_Admin_Token","relationType":"validates_with"}
{"type":"relation","from":"UI_Scrape_Progress_Panel","to":"Endpoint_Scrape_Logs","relationType":"consumes"}
{"type":"relation","from":"Route_Admin_Scrape","to":"UI_Scrape_Progress_Panel","relationType":"renders"}
{"type":"relation","from":"Bug_Worker_SIGKILL_Lost_Run_Fixed","to":"Resume_Checkpoint_Mechanism","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Worker_SIGKILL_Lost_Run_Fixed","to":"Worker_Ready_Hook","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Beat_Double_Fire_Fixed","to":"Redis_Singleton_Lock","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Inspect_Slow_Queue_Fixed","to":"Queue_Optimised_DB","relationType":"resolved_by"}
{"type":"relation","from":"Bug_RealEstate_Outliers_Fixed","to":"Quartirography_Filter_Fix","relationType":"resolved_by"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Session_End_Apr27_2026","relationType":"follows"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Recommend_Level1_Apr27","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Photo_Storage_Pipeline","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Resume_Checkpoint_Mechanism","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"UI_Scrape_Progress_Panel","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Bug_Worker_SIGKILL_Lost_Run_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Bug_Beat_Double_Fire_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Bug_Inspect_Slow_Queue_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Bug_RealEstate_Outliers_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Limit_District_Median_Null","relationType":"opens_todo"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Limit_District_Geometry","relationType":"opens_todo"}
{"type":"relation","from":"Session_Resume_Recommend_Apr28_2026","to":"Schema_Tables_Map_Apr27","relationType":"extends"}
{"type":"relation","from":"Module_Recommend_Query","to":"Sverdl_Quartirography_Report_Apr27","relationType":"operationalizes"}
{"type":"relation","from":"Module_Recommend_Query","to":"PRINZIP_Strategy_Apr27","relationType":"operationalizes"}
{"type":"relation","from":"Bug_SQLAlchemy_DoubleColon_Cast","to":"Pattern_CAST_AS_Type","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Recommend_500_CAST_Fixed","to":"Bug_SQLAlchemy_DoubleColon_Cast","relationType":"instance_of"}
{"type":"relation","from":"Bug_Recommend_500_CAST_Fixed","to":"Pattern_CAST_AS_Type","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Phase_A_INSERT_500_Fixed","to":"Bug_SQLAlchemy_DoubleColon_Cast","relationType":"instance_of"}
{"type":"relation","from":"Bug_Phase_A_INSERT_500_Fixed","to":"Pattern_CAST_AS_Type","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Phase_A_INSERT_500_Fixed","to":"Resume_Checkpoint_Mechanism","relationType":"blocked"}
{"type":"relation","from":"Bug_Phase_A_INSERT_500_Fixed","to":"Module_Scrape_Log","relationType":"diagnosed_via"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Recommend_Level1_Apr27","relationType":"extends"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Module_Velocity_Baseline","relationType":"uses"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Module_Elasticity_Coef","relationType":"uses"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Module_Required_Price_Factor","relationType":"uses"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Module_Liquidity_Score_24mo","relationType":"uses"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Component_Recommend_Velocity_Panel","relationType":"rendered_by"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Component_Recommend_Liquidity_Chart","relationType":"rendered_by"}
{"type":"relation","from":"Recommend_Velocity_Calculator_Apr28","to":"Feature_Headline_CEO","relationType":"produces"}
{"type":"relation","from":"Module_Velocity_Baseline","to":"Module_Recommend_Query","relationType":"called_by"}
{"type":"relation","from":"Module_Elasticity_Coef","to":"Module_Recommend_Query","relationType":"called_by"}
{"type":"relation","from":"Module_Required_Price_Factor","to":"Module_Recommend_Query","relationType":"embedded_in"}
{"type":"relation","from":"Module_Liquidity_Score_24mo","to":"Module_Recommend_Query","relationType":"embedded_in"}
{"type":"relation","from":"Module_Liquidity_Score_24mo","to":"Component_Recommend_Velocity_Panel","relationType":"duplicated_in"}
{"type":"relation","from":"Component_Recommend_Velocity_Panel","to":"Route_Analytics_Recommend","relationType":"rendered_at"}
{"type":"relation","from":"Component_Recommend_Liquidity_Chart","to":"Route_Analytics_Recommend","relationType":"rendered_at"}
{"type":"relation","from":"Feature_Headline_CEO","to":"Route_Analytics_Recommend","relationType":"rendered_at"}
{"type":"relation","from":"Bug_Velocity_Mix_Static_OPEN","to":"Tier_Alpha_Velocity_Overhaul_TODO","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Velocity_Unrealistic_OPEN","to":"Tier_Alpha_Velocity_Overhaul_TODO","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Velocity_Mix_Static_OPEN","to":"Module_Velocity_Baseline","relationType":"located_in"}
{"type":"relation","from":"Bug_Velocity_Unrealistic_OPEN","to":"Module_Velocity_Baseline","relationType":"located_in"}
{"type":"relation","from":"Tier_Alpha_Velocity_Overhaul_TODO","to":"Recommend_Velocity_Calculator_Apr28","relationType":"improves"}
{"type":"relation","from":"Bug_Lock_Held_Silent_Fixed","to":"TTL_Lock_Reduction","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Lock_Held_Silent_Fixed","to":"Module_Lock_Diagnostic_Logs","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Lock_Held_Silent_Fixed","to":"Endpoint_Release_Lock","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Lock_Held_Silent_Fixed","to":"Param_Force_Trigger","relationType":"resolved_by"}
{"type":"relation","from":"Endpoint_Release_Lock","to":"Redis_Singleton_Lock","relationType":"operates_on"}
{"type":"relation","from":"Param_Force_Trigger","to":"Redis_Singleton_Lock","relationType":"manipulates"}
{"type":"relation","from":"Param_Force_Trigger","to":"Endpoint_Admin_Scrape","relationType":"extends"}
{"type":"relation","from":"Module_Lock_Diagnostic_Logs","to":"Module_Scrape_Log","relationType":"complements"}
{"type":"relation","from":"Module_Lock_Diagnostic_Logs","to":"UI_Scrape_Progress_Panel","relationType":"surfaces_in"}
{"type":"relation","from":"TTL_Lock_Reduction","to":"Redis_Singleton_Lock","relationType":"tunes"}
{"type":"relation","from":"Phase_A_Heartbeat_Tick","to":"Resume_Checkpoint_Mechanism","relationType":"extends"}
{"type":"relation","from":"Phase_A_Heartbeat_Tick","to":"Schema_Resume_Columns","relationType":"writes_to"}
{"type":"relation","from":"Autoclean_Heartbeat_Threshold","to":"Zombie_Autocleanup","relationType":"supersedes"}
{"type":"relation","from":"Autoclean_Heartbeat_Threshold","to":"Schema_Resume_Columns","relationType":"reads_from"}
{"type":"relation","from":"Endpoint_Release_Lock","to":"Auth_Admin_Token","relationType":"validates_with"}
{"type":"relation","from":"Deploy_Cache_State_Apr28","to":"Docker_Multi_Target","relationType":"optimizes"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Session_Resume_Recommend_Apr28_2026","relationType":"follows"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Recommend_Velocity_Calculator_Apr28","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Bug_Phase_A_INSERT_500_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Bug_Recommend_500_CAST_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Bug_Lock_Held_Silent_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Bug_Velocity_Mix_Static_OPEN","relationType":"opens_todo"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Bug_Velocity_Unrealistic_OPEN","relationType":"opens_todo"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Tier_Alpha_Velocity_Overhaul_TODO","relationType":"opens_todo"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Deploy_Cache_State_Apr28","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Bug_SQLAlchemy_DoubleColon_Cast","relationType":"discovers"}
{"type":"relation","from":"Session_Apr28_Calc_Scraper_Apr28_2026","to":"Pattern_CAST_AS_Type","relationType":"establishes"}
{"type":"relation","from":"Geo_District_Mapping_Apr29","to":"Module_Fetch_Ekb_Districts","relationType":"uses"}
{"type":"relation","from":"Geo_District_Mapping_Apr29","to":"Schema_Ekb_Districts_Geom","relationType":"requires"}
{"type":"relation","from":"Geo_District_Mapping_Apr29","to":"Schema_Kn_Objects_District_Column","relationType":"requires"}
{"type":"relation","from":"Geo_District_Mapping_Apr29","to":"File_Ekb_Districts_Geojson_Cache","relationType":"produces"}
{"type":"relation","from":"Geo_District_Mapping_Apr29","to":"Module_Backfill_District_Names_Scraper","relationType":"extends_by"}
{"type":"relation","from":"Geo_District_Mapping_Apr29","to":"Pattern_OSM_Overpass_Admin_Level","relationType":"applies"}
{"type":"relation","from":"Module_Fetch_Ekb_Districts","to":"File_Ekb_Districts_Geojson_Cache","relationType":"writes_to"}
{"type":"relation","from":"Module_Fetch_Ekb_Districts","to":"Schema_Ekb_Districts_Geom","relationType":"writes_to"}
{"type":"relation","from":"Module_Fetch_Ekb_Districts","to":"Pattern_OSM_Overpass_Admin_Level","relationType":"applies"}
{"type":"relation","from":"Module_Backfill_District_Names_Scraper","to":"Schema_Ekb_Districts_Geom","relationType":"reads_from"}
{"type":"relation","from":"Module_Backfill_District_Names_Scraper","to":"Schema_Kn_Objects_District_Column","relationType":"writes_to"}
{"type":"relation","from":"Module_Backfill_District_Names_Scraper","to":"Module_Scraper_Kn","relationType":"embedded_in"}
{"type":"relation","from":"Module_Backfill_District_Names_Scraper","to":"Resume_Checkpoint_Mechanism","relationType":"runs_after"}
{"type":"relation","from":"Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed","to":"Geo_District_Mapping_Apr29","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed","to":"Schema_Kn_Objects_District_Column","relationType":"resolved_by"}
{"type":"relation","from":"Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed","to":"Module_Recommend_Query","relationType":"located_in"}
{"type":"relation","from":"Module_Graceful_Obj_Class_Degrade","to":"Bug_Kn_API_Obj_Class_Always_Null_OPEN","relationType":"workarounds"}
{"type":"relation","from":"Module_Graceful_Obj_Class_Degrade","to":"Module_Recommend_Query","relationType":"embedded_in"}
{"type":"relation","from":"Bug_Kn_API_Obj_Class_Always_Null_OPEN","to":"Module_Scraper_Kn","relationType":"located_in"}
{"type":"relation","from":"Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN","to":"Module_Scraper_Kn","relationType":"located_in"}
{"type":"relation","from":"Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN","to":"Limit_District_Median_Partial","relationType":"blocks_full_resolution_of"}
{"type":"relation","from":"Backfill_District_Median_From_Kn_Flats","to":"Schema_Kn_Objects_District_Column","relationType":"depends_on"}
{"type":"relation","from":"Backfill_District_Median_From_Kn_Flats","to":"Limit_District_Median_Partial","relationType":"partially_resolves"}
{"type":"relation","from":"Limit_District_Median_Partial","to":"Limit_District_Median_Null","relationType":"supersedes"}
{"type":"relation","from":"Limit_District_Geometry_Closed","to":"Limit_District_Geometry","relationType":"supersedes"}
{"type":"relation","from":"Limit_District_Geometry_Closed","to":"Geo_District_Mapping_Apr29","relationType":"resolved_by"}
{"type":"relation","from":"Component_Recommend_Page_Reorder_Apr29","to":"Route_Analytics_Recommend","relationType":"rendered_at"}
{"type":"relation","from":"Component_Recommend_District_KPI_Strip","to":"Route_Analytics_Recommend","relationType":"rendered_at"}
{"type":"relation","from":"Component_Recommend_District_KPI_Strip","to":"Schema_Kn_Objects_District_Column","relationType":"displays_data_from"}
{"type":"relation","from":"Component_Recommend_District_KPI_Strip","to":"Module_Recommend_Query","relationType":"consumes_output_of"}
{"type":"relation","from":"Cleanup_Unused_Vars_Recommend","to":"Component_Recommend_Page_Reorder_Apr29","relationType":"complements"}
{"type":"relation","from":"Pricing_Slider_Range_Expanded_Apr29","to":"Component_Recommend_Velocity_Panel","relationType":"modifies"}
{"type":"relation","from":"Pricing_Slider_Range_Expanded_Apr29","to":"Schema_Recommend_IO","relationType":"modifies"}
{"type":"relation","from":"Module_Recommend_Query","to":"Schema_Kn_Objects_District_Column","relationType":"filters_by"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Session_Apr28_Calc_Scraper_Apr28_2026","relationType":"follows"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Geo_District_Mapping_Apr29","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Bug_Recommend_Addr_ILIKE_Returns_Zero_Fixed","relationType":"closes"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Limit_District_Geometry_Closed","relationType":"closes"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Limit_District_Median_Partial","relationType":"partially_closes"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Bug_Kn_API_Obj_Class_Always_Null_OPEN","relationType":"opens_todo"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Bug_Kn_Flats_Price_Per_M2_Sparse_OPEN","relationType":"opens_todo"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Component_Recommend_Page_Reorder_Apr29","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Component_Recommend_District_KPI_Strip","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Pricing_Slider_Range_Expanded_Apr29","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_GeoMapping_Apr29_2026","to":"Backfill_District_Median_From_Kn_Flats","relationType":"highlights_deliverable"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"NSPD_Scrape_Complete_Apr30","relationType":"delivered"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"Cad_Buildings_Schema_v2","relationType":"delivered"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"Cad_Quarter_Backfill_Apr30","relationType":"delivered"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"Sprint1_Plan_May2026","relationType":"produced"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"Sprint2_Stage1_Generative","relationType":"produced"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"Sprint3_Stage2_SiteFinder","relationType":"produced"}
{"type":"relation","from":"NSPD_Scrape_Complete_Apr30","to":"Cad_Quarter_Scrape_Apr29","relationType":"supersedes"}
{"type":"relation","from":"NSPD_Scrape_Complete_Apr30","to":"NSPD_API_Endpoints_Reference","relationType":"uses"}
{"type":"relation","from":"NSPD_Scrape_Complete_Apr30","to":"Cad_Buildings_Schema_v2","relationType":"populates"}
{"type":"relation","from":"Cad_Quarter_Backfill_Apr30","to":"NSPD_Scrape_Complete_Apr30","relationType":"depends_on"}
{"type":"relation","from":"NSPD_Scrape_Complete_Apr30","to":"Limit_District_Median_Partial","relationType":"closes"}
{"type":"relation","from":"Sprint1_Plan_May2026","to":"NSPD_Scrape_Complete_Apr30","relationType":"industrializes"}
{"type":"relation","from":"Sprint1_Plan_May2026","to":"Open_Limitations_Apr30","relationType":"addresses"}
{"type":"relation","from":"Sprint2_Stage1_Generative","to":"GitHub_Issues_Open_Apr30","relationType":"implements"}
{"type":"relation","from":"Sprint3_Stage2_SiteFinder","to":"GitHub_Issues_Open_Apr30","relationType":"implements"}
{"type":"relation","from":"Sprint3_Stage2_SiteFinder","to":"NSPD_Scrape_Complete_Apr30","relationType":"reuses_data_from"}
{"type":"relation","from":"Excluded_Items_User_Pref","to":"GitHub_Issues_Open_Apr30","relationType":"filters"}
{"type":"relation","from":"Session_End_Apr30_2026","to":"Session_Tier2_Apr29_2026_Late","relationType":"follows"}
{"type":"relation","from":"Open_Limitations_Apr30","to":"Bug_Velocity_Region_Wide_Rosreestr_Fixed_Apr29","relationType":"succeeds"}
{"type":"relation","from":"Module_Objective_Client","to":"Objective_Integration_May07_2026","relationType":"implements"}
{"type":"relation","from":"Module_Objective_Parser","to":"Objective_Integration_May07_2026","relationType":"implements"}
{"type":"relation","from":"Schema_Objective_v2_May07","to":"Objective_Integration_May07_2026","relationType":"backs"}
{"type":"relation","from":"Objective_API_Findings_May07","to":"Schema_Objective_v2_May07","relationType":"informs"}
{"type":"relation","from":"Objective_API_Findings_May07","to":"Module_Objective_Parser","relationType":"informs"}
{"type":"relation","from":"Module_Objective_Parser","to":"Schema_Objective_v2_May07","relationType":"writes_into"}
{"type":"relation","from":"Module_Objective_Client","to":"Module_Scraper_Stealth","relationType":"alternative_to"}
{"type":"relation","from":"Session_End_May07_2026","to":"Objective_Integration_May07_2026","relationType":"produced"}
{"type":"relation","from":"Session_End_May07_2026","to":"Session_End_Apr30_2026","relationType":"succeeds"}
{"type":"relation","from":"Objective_Integration_May07_2026","to":"DomRf_Kn_Scraper_Apr27","relationType":"complements"}
{"type":"relation","from":"Project_GenDesign","to":"SiteFinder_v0_2_May08","relationType":"deploys"}
{"type":"relation","from":"SiteFinder_v0_2_May08","to":"TechStack_v2.2","relationType":"diverges_from"}
{"type":"relation","from":"SiteFinder_v0_2_May08","to":"MVP_Scope_AreaSelect_Apr25","relationType":"contradicts"}