gendesign/CLAUDE.md
lekss361 3e6cddde33 docs(claude): obsidian as the only knowledge store
- TL;DR header pin: all memory in Obsidian vault, JSONL deprecated,
  no knowledge .md outside vault.
- Workflow: vault-first search step (mcp__obsidian__simple_search)
  before any non-trivial task.
- New post-task step: update vault with bug fix / ADR / runbook /
  session entry.
- Don't-do-these grouped (knowledge / code-git / schema-migrations).
- MEMORY.md gets matching rule (persists across sessions).
2026-05-11 14:19:48 +03:00

23 KiB
Raw Blame History

Instructions for Claude — GenDesign

Эти инструкции читаются автоматически при старте сессии Claude Code в этом репозитории. Они описывают: что за проект, как работать с кодом и инфрой, какие правила и какие "грабли" не наступать. Источник истины для бизнес-знания — Obsidian vault (см. ниже), а этот файл — про сам процесс разработки.


⚠️ TL;DR — обязательно прочитай первым

  1. Все memory / knowledge только в Obsidian vault obsidian.gendsgn.ru (CouchDB) ↔ C:\Users\user\Documents\gendesign-memory (mirror). Доступ через mcp__obsidian__* tools. Для анализа любой задачи и записи любой документации / решения / research — используй ТОЛЬКО vault.

  2. НЕ читай и НЕ пиши в legacy JSONL knowledge graph (memory/memory-gendesign.jsonl) — он deprecated. Файл оставлен в репе как историчекий снапшот, но не отражает текущее состояние.

  3. НЕ создавай новые .md файлы в docs/, notes/, wiki/ репозитория — knowledge живёт только в vault. Исключения для репа: README.md, CLAUDE.md, docs/*-strategy.md (исторические снапшоты бизнес-плана), inline-комментарии в коде.

  4. Workflow для новой задачи:

    1. obsidian_simple_search "<keyword>"  → найди MOC / related entities
    2. obsidian_get_file_contents для нужных → подгрузи контекст
    3. Делай работу в коде
    4. По итогу: append observation / create entity в vault через
       obsidian_patch_content / obsidian_append_content / Write (filesystem fallback)
    
  5. No auto-commit, no --no-verify — пишу сообщение коммита в чат, пользователь коммитит.


Project at a glance

GenDesign — две продуктовые линии: Site Finder (AI-подбор инвест-участков)

  • Generative Design (автогенерация концепций застройки) для девелоперов РФ. Регион Discovery — Свердловская обл. (ЕКБ, ПЗЗ, МСК-66). Live на https://gendsgn.ru/.

Tech stack

Слой Stack
Backend Python 3.12, FastAPI, SQLAlchemy 2.0, GeoAlchemy2, Pydantic v2, Celery + Redis, httpx, Shapely 2, scikit-learn
DB PostgreSQL 16 + PostGIS 3.4 (partitioned rosreestr_deals, GIST на geom, ~50 предметных таблиц)
Frontend Next.js 15 (app router), React 19, TypeScript 5, Tailwind 4, TanStack Query, Leaflet/Mapbox, ECharts
Export WeasyPrint (PDF), ezdxf (DXF), openpyxl (Excel)
Tooling uv (Python deps), ruff, mypy strict (selective), pytest, pre-commit, prettier
Deploy Beget VPS · GitHub Actions → GHCR → SSH → docker-compose · Caddy auto-TLS
Knowledge Obsidian vault на obsidian.gendsgn.ru (Self-hosted LiveSync + CouchDB)

Repository layout

backend/                 FastAPI + Celery (services, scrapers, workers, api/v1/*)
frontend/                Next.js (app router; analytics, admin, concept, site-finder)
data/sql/                ETL артефакты + миграции схемы (numbered NN_*.sql)
ops/                     backup.sh + deploy скрипты
scripts/                 утилиты (migrate_kg_to_obsidian.py, setup-couchdb.sh, etc)
docs/                    стратегические снапшоты (источник истины — Obsidian)
memory/                  legacy JSONL knowledge graph (deprecated)
docker-compose.prod.yml      main стек (backend, frontend, postgres, redis, worker, beat, caddy)
docker-compose.obsidian.yml  obsidian-стек (CouchDB) — деплоится отдельно
.github/workflows/
  deploy.yml             main stack (триггер: backend/**, frontend/**, Caddyfile)
  deploy-obsidian.yml    obsidian stack (триггер: docker-compose.obsidian.yml, scripts/setup-couchdb.sh)

Where knowledge lives — read THIS first

Obsidian vault на obsidian.gendsgn.ru — единственный source of truth для бизнес-знания (268+ entities + relations). Локальная папка vault'а: C:\Users\user\Documents\gendesign-memory.

Структура vault:

  • meta/ — Project_GenDesign, TechStack, NorthStar + setup guides (00_credentials, 01_connect_devices, 02_claude_usage, 03_obsidian_plugins, 04_mcp_obsidian_setup)
  • domains/{domrf,cadastre,rosreestr,analytics,ui,api,geo,infra,sitefinder}/
  • code/{modules,schemas,patterns,hooks,tasks}/
  • decisions/ fixes/ sessions/ sprints/ events/ research/ sources/ feedback/ github/ limitations/
  • MOC.md (Map of Content) в каждой папке + 00_index.md в корне vault'а

MCP для доступа к vault: mcp__obsidian__* tools (см. meta/02_claude_usage.md):

  • obsidian_simple_search — BM25 fulltext (Obsidian syntax: tag:#x, path:, ["yaml"])
  • obsidian_get_file_contents / obsidian_batch_get_file_contents
  • obsidian_list_files_in_dir
  • obsidian_patch_content (под heading) / obsidian_append_content
  • obsidian_complex_search (JsonLogic)

При работе над задачей: сначала obsidian_simple_search по ключевому слову → найди MOC или related entity → читай target файл. Это в 5-10 раз дешевле по токенам чем Grep + Read по всему репо.

Setup & dev commands

# Локально (Docker Desktop + Node 20 + uv):
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
docker compose up -d --build
curl http://localhost:8000/health   # → {"status":"ok","environment":"dev"}

# Backend dev (без Docker):
cd backend && uv sync
uv run uvicorn app.main:app --reload

# Frontend dev:
cd frontend && npm install && npm run dev

# Migrations (Alembic — стандартный путь):
make migration NAME=add_foo_column
# или сырой SQL (data/sql/NN_xxx.sql) — для DDL артефактов которые
# не сделаны Alembic'ом (большие views, материализации, partitions).

# Tests:
cd backend && uv run pytest
cd frontend && npm test

# Lint + typecheck (запускается в pre-commit, но можно явно):
cd backend && uv run --no-project --with ruff ruff check app/
cd backend && uv run mypy app/services/generative app/services/site_finder/scorer
cd frontend && npx tsc --noEmit -p tsconfig.json
cd frontend && npm run lint

# Codegen TS типов из Pydantic OpenAPI:
cd frontend && npm run codegen

Code style & conventions

Python (backend)

  • Line length 100 (ruff)
  • Ruff rules: E F I B UP N RUF ASYNC; ignored RUF001/002/003 (Cyrillic в комментариях — нормально)
  • mypy strict только для app.services.generative.* и app.services.site_finder.scorer (см. Validation_Findings_Apr25 entity в vault)
  • psycopg v3 only (psycopg[binary]>=3.2.0) — НЕ психcopg2 (его нет в зависимостях; импорт упадёт ModuleNotFoundError). Для bulk INSERT use cur.executemany() или COPY, НЕ execute_values.
  • Type hints везде, Any — только обоснованно
  • Docstrings на русском OK (но без emoji-spam), bullet-факты предпочтительнее художественного описания
  • Async: FastAPI handlers — async def, Celery tasks — def (Celery sync)
  • Tests: pytest + asyncio_mode = auto

Frontend (TS/React)

  • Prettier + ESLint (запускается в pre-commit)
  • React 19 + Next 15 app router (НЕ pages router)
  • TanStack Query для data-fetching, без useEffect для HTTP
  • TS strict, никаких any; для unknown shape → unknown + narrow
  • Styling: Tailwind 4 утилитарные классы, inline styles только для динамики
  • TanStack Query keys как массивы: ["scrape-logs", scraperType, runIdFilter]

SQL

  • Файлы в data/sql/ именуются NN_topic.sql (NN = sequential int, e.g. 78_drop_use_rosreestr2coord.sql)
  • BEGIN ... COMMIT для DDL чтобы атомарно
  • IF EXISTS / IF NOT EXISTS для идемпотентности
  • Комментарии в начале файла: контекст + порядок применения + dependencies
  • View'ы пересоздаются CREATE OR REPLACE VIEW
  • Колонки удаляются ALTER TABLE ... DROP COLUMN IF EXISTS (после удаления зависимостей)

Git workflow

Branches

  • main — protected, triggers prod deploy on push
  • Feature branches: feat/short-description / fix/short-description
  • Trunk-based, мелкие PR'ы (1-2 файла или 1 концептуальное изменение)

Commit messages

  • Imperative mood: "fix worker crash" не "fixed worker crash"
  • Длинный prefix: feat(scope): ..., fix(scope): ..., refactor(scope): ..., docs(scope): ..., chore: ...
  • Body — почему, не что (что видно в diff)
  • Атомарные коммиты — один логический шаг = один коммит

PR review

  • Обязательный self-review перед request review
  • Описание PR: links на issue / vault entity, скрин для UI changes
  • Squash on merge

Critical workflow rules (НЕ нарушать)

  1. Никогда не делай git commit сам — пользователь коммитит лично. Ты пишешь сообщение в чат, пользователь применяет.
  2. Никогда не используй --no-verify / --no-edit / --amend — pre-commit hooks обязательны. Если hook падает — fix root cause, не bypass.
  3. Никогда не пуш с --force в main — катастрофа для всей команды.
  4. Не вызывай destructive команды без явного approval: git reset --hard, git clean -fdx, DROP TABLE, TRUNCATE, rm -rf за пределами node_modules/.next.

Pre-commit hooks

Запускаются автоматически при git commit. Если упали — не обходи через --no-verify. Пиши код сразу под hooks:

  • ruff — line ≤100, типичные Python issues
  • prettier — frontend formatting
  • no large files (>500 KB)
  • trailing whitespace / end-of-file fixer
  • mixed-line-ending (LF only в репе)
  • detect-private-key (защита от случайного коммита ключей)

Если pre-commit перепишет файл (auto-fix) — нужно git add повторно и git commit.

Database & migrations

Подключение к prod DB

Доступ через SSH-tunnel (порт 15432 на ноуте → 5432 на VPS, см. ~/.ssh/config):

# Tunnel поднимается автоматом при `ssh gendesign` (LocalForward в config),
# или вручную:
ssh -N gendesign

# Подключение psql:
psql postgresql://gendesign:<password>@localhost:15432/gendesign

Credentials — в Obsidian vault meta/00_credentials.md (НЕ в этом файле, НЕ в коммитах!).

Migration pattern

  1. Alembic migrations для prod schema changes (backend/alembic/versions/).
  2. Raw SQL artifacts (data/sql/NN_xxx.sql) для:
    • Bootstrap / dev seed
    • Большие view с UNION
    • Material partitions / GIST индексы
    • Удалить колонку с CASCADE-зависимостями

Applying migrations к prod

Order matters:

  1. Apply migration first (SQL → prod)
  2. Deploy backend code that matches new schema
  3. Никогда наоборот — иначе deployed code напорется на старую/новую несовместимую схему

Если миграция меняет существующие FK / column type / drop column — read-then-write дискретно: верифицируй на staging, имей rollback ready.

Postgres MCP

Доступ из Claude к prod DB через mcp__postgres-gendesign__* tools (после SSH tunnel). Для прод-чтения нужен explicit approval — safety guard для production reads.

Deploy

GitHub Actions:

  • .github/workflows/deploy.yml — main: build & push backend (lean + worker-with-chromium) + frontend → SSH → compose pull && up -d + caddy reload + /health check
  • .github/workflows/deploy-obsidian.yml — obsidian: SSH compose up -d для couchdb + idempotent scripts/setup-couchdb.sh bootstrap

Триггеры по path:

  • Push в backend/**, frontend/**, Caddyfile, docker-compose.prod.ymldeploy.yml
  • Push в docker-compose.obsidian.yml, scripts/setup-couchdb.sh, docs/obsidian-livesync.mddeploy-obsidian.yml
  • Push только в data/sql/** или docs/** (не из триггеров выше) — деплоев не вызывает

Sentry release tracking: SENTRY_RELEASE=$IMAGE_TAG пишется в backend/.env.runtime на VPS через sed (НЕ полная перезапись файла — там user-managed COUCHDB_PASSWORD и пр.).

When working on a task

1. Understand context — ВСЕГДА vault-first

  • Прочитай user request один раз
  • mcp__obsidian__obsidian_simple_search "<keyword>" — обязательный первый шаг для нетривиальной задачи. Найди MOC + related entities.
  • Открой связанный MOC.md (например domains/domrf/domrf-MOC.md для DOM.РФ работы) — он покажет relevant entities
  • Если в vault'е есть fixes/Bug_X.md про похожую проблему — обязательно прочитай
  • НЕ ищи в memory/memory-gendesign.jsonl — он deprecated, состояние не отражает

2. Plan, then act

  • Для нетривиальных задач (>3 файла или >50 строк) — сначала набросай план (или используй Plan subagent), потом выполняй
  • Для тривиальных (typo, mass-rename, обновить deps) — сразу делай

3. Verify locally

  • ruff + tsc + ast.parse() где применимо
  • Не пиши тесты пока user не попросил, НО не ломай существующие
  • Pre-commit hooks упадут на CI → проверь локально через pre-commit run --all-files если делал большие изменения

4. Communicate

  • Не объясняй очевидное (если правил один файл — не нужен абзац summary)
  • Для каждого fix: что было сломано, что починил, что осталось проверить пользователю
  • Если изменения в нескольких репо/системах — финальный bullet-list "Что осталось у тебя"

5. Commit message

  • Когда задача готова — напиши сообщение коммита в чат (не коммить сам)
  • Conventional commits style + краткое описание зачем

6. Update vault (важно!)

Для нетривиальных изменений — обнови vault:

  • Bug fix → создай или обнови fixes/Bug_<short_name>.md с root cause + fix
  • ADR / architectural decision → создай decisions/<Name>.md
  • Новый scraper / endpoint / module → создай entity в domains/<area>/ или code/modules/
  • Гайд по операционной задачеrunbooks/ (или в meta/0X_*.md если про сам repo / workflow)
  • Session log (опционально для большой работы): sessions/Session_<date>_<topic>.md

Используй mcp__obsidian__obsidian_append_content для добавления observation в existing entity, либо Write напрямую в C:\Users\user\Documents\gendesign-memory\<path>/<File>.md (LiveSync запушит в CouchDB через ~60 сек).

Common pitfalls (learned the hard way)

Worker crash на старте

  • Скорее всего import error — pyproject.toml имеет dep, но uv.lock ещё не обновлён
  • Fix: cd backend && uv lock → коммит lock-файла → push → CI пересобирает image

psycopg2 ImportError

  • В проекте только psycopg v3. Если видишь import psycopg2 — порти.
  • psycopg2.extras.execute_valuescur.executemany() (v3 pipeline mode справится)

Caddy не подхватывает Caddyfile после up -d

  • Caddyfile bind-mounted — нужен явный caddy reload
  • deploy.yml это делает после compose up -d

git pull на VPS перетирает локальные правки

  • deploy.yml использует git reset --hard origin/main — любые ручные правки в /opt/gendesign будут стёрты
  • .env-файлы выживают (они в .gitignore)

docker compose restart не перечитывает env_file

  • После правки .env: up -d --force-recreate --no-deps <service>

Frontend build хочет TS-типы которых нет

  • npm run codegen обновляет src/types/openapi.ts из live OpenAPI schema backend'а
  • Если backend меняется → нужно перегенерить TS типы

NSPD WAF / rate limiting

  • Используй rosreestr2coord lib (v5+), НЕ свой urllib
  • Rate limit делается worker'ом (time.sleep(rate_ms / 1000)), НЕ библиотекой (в v5 убрали delay параметр)

CouchDB / LiveSync — данные не появляются в Obsidian

  • Local vault на ноуте — single source of write
  • Если LiveSync не запушил после изменения → команда Self-hosted LiveSync: Replicate now
  • Если file body пустой → Verify and repair all files → Apply Remote (см. 04_mcp_obsidian_setup.md)

git status показывает trailing-whitespace / line-ending warnings

  • Это от core.autocrlf на Windows. Pre-commit mixed-line-ending hook fix'ит автоматом.

Don't do these (no exceptions)

Knowledge / memory

  • Читать или писать в memory/memory-gendesign.jsonl — он deprecated. Knowledge только в Obsidian vault.
  • Создавать новые .md для knowledge вне vault'а — никаких docs/research/*.md, notes/, wiki/ etc. Всё что про предметную область → vault.
  • Использовать aim_memory_* MCP tools (старая knowledge-graph MCP server'а нет, поэтому даже не пытайся).
  • Удалять MOC.md файлы в vault'е — они нужны для навигации.
  • Писать новые сущности в old/ папку vault'а — это архив legacy paths.

Code / git

  • Commit сам через git commit — пользователь коммитит лично, я пишу сообщение в чат.
  • --no-verify, --amend, --no-edit, --no-gpg-sign — обходить hooks/signing нельзя.
  • git push --force в main или shared branches.
  • Hardcode credentials в код / в коммиты. Используй os.environ.get() + .env/.env.runtime.
  • print(...) для логирования в prod-коде — использовать logger.info/warning/error.
  • Catching Exception без re-raise или явного логирования (silent failures).
  • Использовать requests напрямую — есть httpx в стеке.
  • Импортировать psycopg2 — в проекте только psycopg v3.

Schema / migrations

  • Запускать миграции на prod без понимания зависимостей (views на колонки, FK).
  • Менять categorize_v2 в scripts/migrate_kg_to_obsidian.py без сопутствующей миграции (path scheme должен оставаться backwards-compatible).
  • DROP TABLE / TRUNCATE без явного approval пользователя.

Token efficiency tips для Claude

  • Не читай 00_index.md → каждый entity по списку — это 268 read'ов, ~500K токенов. Иди через MOC + tags.
  • grep -l (или Grep с output_mode: files_with_matches) дешевле полного content reading.
  • Один obsidian_simple_search часто заменяет 3-5 Read + parse.
  • При write — обновляй MOC.md только если структурное изменение (новый entity, переименование, удаление). Append observation в existing entity не требует MOC update.
  • Когда видишь много [[wiki-links]]НЕ читай каждый, спроси у user'а что именно интересует.

Project-specific knowledge to load on first read

При старте новой задачи в этом репо — first principles в vault'е:

  • meta/02_claude_usage.md — этот гайд (источник истины — vault'овая копия)
  • meta/00_credentials.md — secrets (когда нужны для debug-задач)
  • decisions/ папка — почему мы делаем так а не иначе (ADR-style)
  • fixes/ папка — что уже ломалось и как чинили
  • limitations/ папка — что НЕ работает / не реализовано

Для специфичной работы — открывай MOC по релевантному домену (domains/<area>/<area>-MOC.md).


Maintenance: этот файл обновляется когда:

  • Меняется tech stack (миграция фреймворка / DB)
  • Появляются новые workflow rules (новые hooks, новые workflow в CI)
  • Команда сталкивается с recurring pitfall → запиши его в "Common pitfalls"
  • Меняется структура vault'а / MOC scheme

Не превращай в новеллу — держи функциональный, action-oriented, без воды.