diff --git a/memory/memory-gendesign.jsonl b/memory/memory-gendesign.jsonl index 5198493d..664af2e2 100644 --- a/memory/memory-gendesign.jsonl +++ b/memory/memory-gendesign.jsonl @@ -266,6 +266,7 @@ {"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= → JSON {token: '...'}. GetReport на /v2/Report/GetReport?Page=Отчеты&ReportSection=Объединенные данные&ReportType=...&ReportName=...&GroupName=...&[ComplexName]&[StartDate]&[EndDate]&[UseDdu]&[UseDkp]. Auth: Authorization: Bearer . 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= uv run python -X utf8 ../data/sql/69b_objective_minimal.py [--no-complex --days 3 | --only corp_sum]. Сохраняет в data/raw/objective_test//.","ФИНАЛЬНЫЕ файлы изменены 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"} @@ -910,4 +911,4 @@ {"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":"Objective_Integration_May07_2026","to":"DomRf_Kn_Scraper_Apr27","relationType":"complements"} \ No newline at end of file