gendesign/CLAUDE.md
lekss361 485c221c3b
docs(claude): formalize Auto-review passed as approval signal (#85)
* docs(claude): formalize "Auto-review passed" as approval signal + polling loop

Per user feedback after PR #84 merge:
- Critical rule 5: "Auto-review passed" / "LGTM" от auto-review bot = approval
  (наряду с явным "merge it" / "approved" от human user)
- Add "Polling loop для PR" section: 60s ScheduleWakeup pattern,
  decisive states (merged / approved / changes / no-news), cap 30 iters

This formalizes what main session already did: after fixup commit, poll
comments, detect auto-review verdict, and auto-merge if passed.

* fix(claude): address PR #85 auto-review feedback

- Fix cyrillic/latin typo (rule 5 second sub-bullet)
- Add SHA marker validation to polling loop (race condition on stale LGTM after fixup-push)
- Add explicit "Auto-merge scope" rule 6 — allowlist (docs/UI/.claude) vs blocklist (migrations/API/infra/secrets)
- Sync "Когда auto-mode" section with new merge approval signals
- Lower cap to 5 iters for scope-blocked PRs (human required anyway)
- Self-modifying CLAUDE.md rules → always require human

Per auto-review on e66e1ea.

---------

Co-authored-by: lekss361 <claudestars@proton.me>
2026-05-12 00:43:25 +03:00

550 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.

# 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. **Branch + PR workflow обязательно** — никаких direct push в main. Создаю feature branch (`feat/...` / `fix/...` / `refactor/...` / `docs/...` / `chore/...`), коммичу туда, push branch, `gh pr create`, отдаю URL пользователю. Merge только по явному approval. См. секцию "Git workflow".
6. **No `--no-verify` / `--force` / `--amend`** — pre-commit hooks обязательны, force-push запрещён.
---
## 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
```bash
# Локально (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 — BRANCH + PR mandatory
### Workflow (НИКАКОГО direct push в main)
```
1. Создаём feature branch: git checkout -b feat/foo-bar
2. Commits на этой ветке: git commit -m "..."
3. Push branch: git push -u origin feat/foo-bar
4. Создаём PR: gh pr create --title "..." --body "..."
5. Show PR URL пользователю → ждём review
6. Пользователь комментирует / approves
7. После approval — пользователь merge'ит (или я merge'у после явного "merge it")
8. Удаляем branch после merge
```
### Branches
- `main` — protected, **никаких direct push**. Только через PR merge.
- Feature branches: `feat/short-description` / `fix/short-description` / `refactor/...` / `docs/...` / `chore/...`
- Trunk-based, мелкие PR'ы (1-2 файла или 1 концептуальное изменение)
### Commit messages (на feature branch)
- Imperative mood: "fix worker crash" не "fixed worker crash"
- Длинный prefix: `feat(scope): ...`, `fix(scope): ...`, `refactor(scope): ...`, `docs(scope): ...`, `chore: ...`
- Body — почему, не что (что видно в diff)
- Атомарные коммиты — один логический шаг = один коммит
- НЕ добавлять `Co-Authored-By: Claude ...` (per feedback rule)
### PR
- Title: краткое описание изменения (под 70 символов)
- Body должен содержать:
- `## Summary` — 1-3 bullet'a что изменилось
- `## Test plan` — что проверить пользователю / какие команды smoke test'а
- Cross-refs: `Closes #N`, `Relates to #N`, ссылка на vault entity
- `gh pr create` с `--title` + `--body` (через HEREDOC чтобы preserve formatting)
- После создания — **вернуть PR URL пользователю**, ждать его approval
- **Squash on merge** — PR в main объединяется одним коммитом через squash (предпочтительно `gh pr merge --squash`).
### Code review pipeline
```
Worker (backend/frontend/database/devops) пишет код на feature branch
Main session делает commit на feature branch (worker'у запрещено git commit)
[опционально] code-reviewer agent делает review
↓ если ✅
git push -u origin feat/branch
gh pr create → PR URL пользователю
User approves / requests changes
Если changes — main session делает fixup commits на той же branch + push
По явному "merge it" / "approved" от user → gh pr merge --squash
```
### Critical workflow rules (НЕ нарушать)
1. **НИКОГДА не пуш напрямую в main.** Только через PR merge.
2. **Worker-agents (backend/frontend/devops/database) НЕ делают `git commit` сами.** Они оставляют изменения staged — main session коммитит на feature branch.
3. **Никогда не используй `--no-verify` / `--no-edit` / `--amend`** — pre-commit hooks обязательны. Если hook падает — fix root cause, не bypass.
4. **Никогда не пуш с `--force` ни в main ни в feature branch без approval.**
5. **Merge PR только по approval.** Approval сигналы:
- **Human user всегда валиден:** "merge it" / "ok merge" / "approved" / "залей" / "мердж"
- **Auto-review bot LGTM = approval, НО с ограничениями** (см. "Auto-merge scope" ниже). Bot LGTM валиден **только** если SHA marker в теле комментария совпадает с current PR HEAD SHA — иначе это устаревший approval до fixup-push.
6. **Auto-merge scope (где боту разрешено self-merge без человека):**
- ✅ **Разрешено** (PR diff целиком в этих путях):
- `CLAUDE.md`, `README.md`, `docs/**` (документация / правила)
- `frontend/src/app/**` UI-only changes без новых API endpoints
- `frontend/public/**` (статика)
- `.claude/agents/**`, `memory/feedback_*.md` (workflow rules)
- ❌ **Запрещено — нужен human approval** (любой файл из списка → block auto-merge):
- `data/sql/**`, `backend/alembic/versions/**` (миграции / схема DB)
- `backend/app/api/v1/**`, `backend/app/services/**` (бизнес-логика API)
- `backend/app/scrapers/**` (внешние интеграции)
- `docker-compose*.yml`, `Caddyfile`, `.github/workflows/**` (deploy / infra)
- Любые файлы с упоминанием secret / token / password / credential / X-Admin-Token
- PRs которые меняют `CLAUDE.md` рядом с `Critical workflow rules` / `Auto-merge scope` / auth — это саморасширение правил, **нужен human**
- Если PR touches both — берётся more restrictive (block).
7. **Не вызывай destructive команды без явного approval**: `git reset --hard`, `git clean -fdx`, `DROP TABLE`, `TRUNCATE`, `rm -rf` за пределами `node_modules/.next`.
### Polling loop для PR
После создания PR / fixup commits — запускай ScheduleWakeup с 60с интервалом:
1. `gh pr view <N> --json state,mergeable,comments,headRefOid` → возьми `headRefOid` (current SHA) и latest_comment.
2. `state == MERGED` → stop polling.
3. **Approval check** (новый comment от auto-review):
- Распарси HTML marker: `<!-- gendesign-review-bot: sha=<sha7> verdict=<approve|changes> -->`
- **SHA guard:** `marker.sha7 == headRefOid[:7]` — иначе это устаревший approval до fixup-push, игнорируй.
- **Scope guard:** проверь `gh pr view <N> --json files` — если хоть один путь попадает в "запрещённый" список (см. rule 6 "Auto-merge scope") → block auto-merge, ping user.
- `verdict=approve` + SHA match + scope OK → `gh pr merge <N> --squash --delete-branch`, stop.
- Если в комменте только текст "Auto-review passed" / "LGTM" без HTML marker — НЕ доверяй (legacy / поддельный сигнал), ping user.
4. `verdict=changes` → fixup commits на той же ветке, push, reply, re-poll.
5. Нет новых комментов с last polled timestamp → re-schedule 60с poll.
6. **Cap:** 30 итераций без resolution → stop, ask user. Для PR со scope-запрещёнными файлами cap = 5 итераций (не имеет смысла долго ждать, всё равно нужен human).
### Когда auto-mode
Даже в auto-mode НЕ пушим в main без PR. Auto-mode позволяет:
- Создавать feature branches автономно
- Делать commits на feature branch (main session делает, не worker'ы)
- `git push -u origin <feature-branch>`
- `gh pr create`
- Прогонять code-reviewer
- **Auto-merge** через `gh pr merge --squash` — только если PR в "Auto-merge scope ✅" (см. rule 6) И auto-review bot вернул `verdict=approve` с валидным SHA marker.
- **Финальный merge для PR из scope ❌** (миграции / API / infra / secrets) — только по явному approval от пользователя ("merge it" / "залей" / etc).
## 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`):
```bash
# 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.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/` лежит 6 subagent'ов — 4 worker'a + 2 read-only (analyst, reviewer). Каждый имеет:
- Свой 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 |
### Read-only (2) — не пишут код
| Agent | Когда использовать |
|---|---|
| **tech-analyst** (yellow) | Нечёткий запрос ("надо ускорить", "что чинить дальше"), cross-domain задачи (2+ слоя), рефакторинг-разборы, аудит. Возвращает план, main session раздаёт worker'ам. |
| **code-reviewer** (red) | Review ПОСЛЕ worker'а ДО `git push`. Проверяет: security (secrets, SQL injection, auth bypass), correctness (edge cases, transactions, idempotency), performance (N+1, индексы, re-renders), conventions (ruff/prettier/CLAUDE.md), arch (DRY, dead code). Возвращает verdict ✅/⚠️/❌. |
### 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'ам по плану
- **После worker'а перед push критичных изменений** → `code-reviewer` → если ❌ блок → вернуть worker'у. Опционально для тривиальных.
- **Pure exploration** (поиск файлов / понимание структуры) — встроенный `Explore` (Haiku, дёшево)
- **Crisis fix** (горящий prod баг) — пропускаешь tech-analyst и code-reviewer, идёшь напрямую к 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'а + 2 read-only (tech-analyst планирует, code-reviewer проверяет) — read-only не считаются worker'ами.
### Code-reviewer workflow
```
User request → tech-analyst (если cross-domain)
Main session creates feature branch (git checkout -b feat/...)
Worker (backend/frontend/devops/database) пишет код (staged changes)
**code-reviewer** проверяет staged changes:
• ✅ APPROVE → main session коммитит на feature branch
• ⚠️ MINOR → main session решает (или коммитит, или возвращает worker'у)
• ❌ MAJOR → BLOCK, возвращает worker'у на исправление
Loop until ✅ → git push -u origin <feature-branch>
gh pr create → отдаём PR URL пользователю
По явному "merge it" / "approved" → gh pr merge --squash --delete-branch
```
Используй code-reviewer для:
- Backend endpoints (auth, SQL injection vector)
- DB migrations (idempotency, индексы)
- Production deploys (compose changes, secrets)
- Изменения в job_settings / async tasks (race conditions)
Можно пропустить для:
- UI-only style/cosmetic
- Documentation
- Frontend type tweaks
- Trivial fixes (typo, rename)
### 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 строк) — **сначала набросай план** (или используй `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_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-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
- ❌ **Direct push в main** — только через PR. Все изменения на feature branch → `gh pr create` → user approval → merge. См. "Git workflow".
- ❌ **Merge PR без явного user approval** ("merge it" / "approved" / "ok merge").
- ❌ `--no-verify`, `--amend`, `--no-edit`, `--no-gpg-sign` — обходить hooks/signing нельзя.
- ❌ `git push --force` ни в main ни в feature branch без approval.
- ❌ 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, без воды.