Worker agents (write code): - backend-engineer (blue, sonnet) - frontend-engineer (green, sonnet) - devops-engineer (orange, sonnet) - database-expert (purple, sonnet) Analyst/planner (read-only, no code): - tech-analyst (yellow, sonnet) — decomposes vague/cross-domain requests into structured plans for workers. Has read-only tools (Read/Glob/Grep, MCP obsidian/postgres read APIs, WebSearch) but NO Write/Edit/execute_sql/destructive Bash. CLAUDE.md updated: - Workers (4) vs Analyst (1) classification - Routing rules: trivial → main, single-domain → worker direct, vague/cross-domain → tech-analyst first - Cross-domain orchestration pattern with explicit flow Each agent file: - Pre-loaded vault MOC pointers for the domain - Tech stack + conventions specific to the layer - 5-8 critical pitfalls from real bugs this sprint - Explicit deny-list of cross-scope operations
26 KiB
Instructions for Claude — GenDesign
Эти инструкции читаются автоматически при старте сессии Claude Code в этом репозитории. Они описывают: что за проект, как работать с кодом и инфрой, какие правила и какие "грабли" не наступать. Источник истины для бизнес-знания — Obsidian vault (см. ниже), а этот файл — про сам процесс разработки.
⚠️ TL;DR — обязательно прочитай первым
-
Все memory / knowledge только в Obsidian vault
obsidian.gendsgn.ru(CouchDB) ↔C:\Users\user\Documents\gendesign-memory(mirror). Доступ черезmcp__obsidian__*tools. Для анализа любой задачи и записи любой документации / решения / research — используй ТОЛЬКО vault. -
НЕ читай и НЕ пиши в legacy JSONL knowledge graph (
memory/memory-gendesign.jsonl) — он deprecated. Файл оставлен в репе как историчекий снапшот, но не отражает текущее состояние. -
НЕ создавай новые
.mdфайлы вdocs/,notes/,wiki/репозитория — knowledge живёт только в vault. Исключения для репа:README.md,CLAUDE.md,docs/*-strategy.md(исторические снапшоты бизнес-плана), inline-комментарии в коде. -
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) -
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_contentsobsidian_list_files_in_dirobsidian_patch_content(под heading) /obsidian_append_contentobsidian_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; ignoredRUF001/002/003(Cyrillic в комментариях — нормально) - mypy
strictтолько дляapp.services.generative.*иapp.services.site_finder.scorer(см.Validation_Findings_Apr25entity в vault) - psycopg v3 only (
psycopg[binary]>=3.2.0) — НЕ психcopg2 (его нет в зависимостях; импорт упадёт ModuleNotFoundError). Для bulk INSERT usecur.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 (НЕ нарушать)
- Никогда не делай
git commitсам — пользователь коммитит лично. Ты пишешь сообщение в чат, пользователь применяет. - Никогда не используй
--no-verify/--no-edit/--amend— pre-commit hooks обязательны. Если hook падает — fix root cause, не bypass. - Никогда не пуш с
--forceв main — катастрофа для всей команды. - Не вызывай 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
- Alembic migrations для prod schema changes (
backend/alembic/versions/). - Raw SQL artifacts (
data/sql/NN_xxx.sql) для:- Bootstrap / dev seed
- Большие view с UNION
- Material partitions / GIST индексы
- Удалить колонку с CASCADE-зависимостями
Applying migrations к prod
Order matters:
- Apply migration first (SQL → prod)
- Deploy backend code that matches new schema
- Никогда наоборот — иначе 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+/healthcheck.github/workflows/deploy-obsidian.yml— obsidian: SSHcompose up -dдля couchdb + idempotentscripts/setup-couchdb.shbootstrap
Триггеры по path:
- Push в
backend/**,frontend/**,Caddyfile,docker-compose.prod.yml→deploy.yml - Push в
docker-compose.obsidian.yml,scripts/setup-couchdb.sh,docs/obsidian-livesync.md→deploy-obsidian.yml - Push только в
data/sql/**илиdocs/**(не из триггеров выше) — деплоев не вызывает
Sentry release tracking: SENTRY_RELEASE=$IMAGE_TAG пишется в backend/.env.runtime на VPS через sed (НЕ полная перезапись файла — там user-managed COUCHDB_PASSWORD и пр.).
Specialized subagents
В .claude/agents/ лежит 5 subagent'ов — 4 worker'a + 1 analyst/planner. Каждый имеет:
- Свой context window (не засоряет main session)
- Restricted tool set (не делает что-то вне его scope)
- Pre-loaded knowledge о доменных конвенциях
Workers (4) — пишут код
| Agent | Когда использовать |
|---|---|
| backend-engineer (blue) | Работа в backend/app/ — FastAPI, Celery, scrapers, services, ETL |
| frontend-engineer (green) | Работа в frontend/ — Next.js pages, components, hooks, admin UI |
| devops-engineer (orange) | docker-compose*.yml, Caddyfile, .github/workflows/, deploy issues, SSH operations |
| database-expert (purple) | data/sql/NN_*.sql migrations, Alembic, EXPLAIN ANALYZE, index design, schema changes |
Analyst (1) — планирует, не пишет
| Agent | Когда использовать |
|---|---|
| tech-analyst (yellow) | Нечёткий запрос ("надо ускорить", "что чинить дальше"), cross-domain задачи (2+ слоя), рефакторинг-разборы, аудит. Read-only — возвращает план, главный session раздаёт worker'ам. |
Routing rules
- Тривиальная задача (typo, rename, обновить one-liner) — main session сам, без делегирования
- Single-domain task с чёткими шагами → один соответствующий worker через
Agent(subagent_type="backend-engineer", ...) - Нечёткая задача / cross-domain (2+ слоя) → сначала
tech-analyst→ план → main session раздаёт worker'ам по плану - Pure exploration (поиск файлов / понимание структуры) — встроенный
Explore(Haiku, дёшево) - Crisis fix (горящий prod баг) — пропускаешь tech-analyst, идёшь напрямую к worker'у
Cross-domain pattern (рекомендуемый)
Для задач затрагивающих 2+ слоя:
User request
↓
tech-analyst → структурированный план: Шаг 1 (database-expert) → Шаг 2 (backend-engineer) → Шаг 3 (frontend-engineer)
↓
Main session (ты) показывает план пользователю → получает approval
↓
Main session запускает worker'ов в order'е (по dependencies)
↓
Каждый worker возвращает summary → main session собирает в финальный отчёт
Что считается "max 4 worker agents"
По best practices (Anthropic, community) — больше 4 worker-агентов снижает productivity (классификация "кто что делает" становится сложнее). У нас 4 worker'а + analyst/planner — последний не считается worker'ом (read-only, не пишет код), а оркестратором.
Subagents не могут спавнить друг друга
Только main session может вызывать subagents через Agent tool. Если worker обнаружил что нужна работа из чужого scope — возвращает control в main session, main делегирует следующему.
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 строк) — сначала набросай план (или используй
Plansubagent), потом выполняй - Для тривиальных (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_values→cur.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-endinghook 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-5Read+ 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, без воды.