* fix(frontend): apiFetchWithStatus body stream double-read crash
Per user report 2026-05-14: 'Failed to execute text on Response: body stream
already read' при analyze с non-JSON error response.
apiFetchWithStatus делал .json() (consumes stream), потом .text() в catch
(FAILS — stream already consumed). Fetch API: body — ReadableStream,
consumable один раз.
Fix: read text() once → JSON.parse on string. На fail (HTML / non-JSON)
оборачиваем в {detail: rawText}. Никаких double-reads.
Site-finder cad search больше не крашится на error pages.
* feat(infra): auto-apply data/sql/*.sql migrations in deploy pipeline (#150)
Закрывает root cause production 500 на /api/v1/admin/site-finder/weight-profiles
(а также 2 unapplied migrations: #89/#91).
## Why это нужно
После audit обнаружили что:
- backend/alembic/versions/ пустой (Alembic configured но не используется)
- deploy.yml не имеет migration step
- 47+ raw SQL files накопилось без auto-apply
- 3 файла unapplied: 87 (engineering), 89 (drop brin), 90 (weight profiles)
User report: GET weight-profiles → 500 потому что user_weight_profiles
table не существует на prod.
## Changes
### deploy.yml +39 lines
- Path trigger расширен на data/sql/*.sql
- New step 'Apply DB migrations' между compose pull и compose up -d:
- Idempotent CREATE TABLE _schema_migrations
- Loop по data/sql/*.sql sorted → skip applied → psql with ON_ERROR_STOP=on
- Record applied filename в tracking table
- Exit 1 на failure → containers НЕ обновляются (no partial state)
### NN collision fix
- 87_engineering_networks_191fz.sql → 91_engineering_networks_191fz.sql
(collision с 87_on_demand_indexes.sql, мой renumber 85→87 был неудачным)
### CLAUDE.md +32 lines
- Subsection 'Auto-apply' под Migration pattern
- Bootstrap procedure docs
- Idempotency requirement
- Failure recovery
### scripts/bootstrap_schema_migrations.sh +100 lines
- One-time seed _schema_migrations с 48 already-applied files
- 3 файла intentionally NOT seeded: 89/90/91 (auto-apply на first deploy)
- Usage docs + verification query
## Vault
domains/infra/Runbook_Auto_Apply_Migrations.md NEW
infra-MOC.md updated
## Required manual steps ДО merge
1. SSH gendesign (tunnel)
2. POSTGRES creds export
3. bash scripts/bootstrap_schema_migrations.sh — seed 48 already-applied files
4. Verify: SELECT COUNT(*) FROM _schema_migrations → 48
5. После merge → first deploy auto-apply #89/#90/#91 → 500 closes
Closes #150
---------
Co-authored-by: lekss361 <claudestars@proton.me>
36 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) -
Branch + PR workflow обязательно — никаких direct push в main. Создаю feature branch (
feat/.../fix/.../refactor/.../docs/.../chore/...), коммичу туда, push branch,gh pr create, отдаю URL пользователю. Merge только по явному approval. См. секцию "Git workflow". -
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_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 — 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 (НЕ нарушать)
- НИКОГДА не пуш напрямую в main. Только через PR merge.
- Worker-agents (backend/frontend/devops/database) НЕ делают
git commitсами. Они оставляют изменения staged — main session коммитит на feature branch. - Никогда не используй
--no-verify/--no-edit/--amend— pre-commit hooks обязательны. Если hook падает — fix root cause, не bypass. - Никогда не пуш с
--forceни в main ни в feature branch без approval. - 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.
- Auto-merge scope (где боту разрешено self-merge без человека):
- ✅ Разрешено (PR diff целиком в этих путях):
CLAUDE.md,README.md,docs/**(документация / правила)frontend/src/app/**UI-only changes без новых API endpointsfrontend/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).
- ✅ Разрешено (PR diff целиком в этих путях):
- Не вызывай destructive команды без явного approval:
git reset --hard,git clean -fdx,DROP TABLE,TRUNCATE,rm -rfза пределамиnode_modules/.next.
Polling loop для PR
После создания PR / fixup commits — запускай ScheduleWakeup с 60с интервалом:
gh pr view <N> --json state,mergeable,comments,headRefOid→ возьмиheadRefOid(current SHA) и latest_comment.state == MERGED→ stop polling.- 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.
- Распарси HTML marker:
verdict=changes→ fixup commits на той же ветке, push, reply, re-poll.- Нет новых комментов с last polled timestamp → re-schedule 60с poll.
- 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):
# 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-зависимостями
Auto-apply (data/sql/*.sql → prod)
data/sql/NN_*.sql миграции применяются автоматически через deploy.yml
после compose pull и до compose up -d. Tracking через _schema_migrations
table в prod DB — каждый файл применяется ровно один раз, в порядке sort (NN order).
При добавлении новой миграции:
- Создаёшь
data/sql/NN_xxx.sql(NN — следующий sequential номер) - Открываешь PR — merge автоматически триггерит deploy
- Deploy auto-apply этого файла + любых других pending
Bootstrap (one-time): до первого auto-deploy после merge PR #150 —
запустить ./scripts/bootstrap_schema_migrations.sh на prod вручную
(через SSH tunnel) чтобы seed tracking table с уже-applied файлами.
Иначе auto-deploy попытается применить все 88 исторических файлов, многие не idempotent.
Idempotency: каждый новый .sql файл должен быть idempotent
(IF NOT EXISTS, ON CONFLICT DO NOTHING, CREATE OR REPLACE VIEW) —
на случай частичного применения или ручного ре-apply.
Если auto-apply падает: deploy завершится с ошибкой (exit 1). Containers
не обновятся. Диагностика: посмотреть GitHub Actions log шага "Apply DB migrations".
Ручной fix: psql -f data/sql/NN_xxx.sql через SSH tunnel, затем вручную
INSERT INTO _schema_migrations (filename) VALUES ('NN_xxx.sql') ON CONFLICT DO NOTHING;,
затем rerun workflow.
Applying migrations к prod
Order matters:
- Apply migration first (SQL → prod) — теперь auto через deploy.yml
- 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,data/sql/*.sql→deploy.yml - Push в
docker-compose.obsidian.yml,scripts/setup-couchdb.sh,docs/obsidian-livesync.md→deploy-obsidian.yml - Push только в
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 строк) — сначала набросай план (или используй
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
- ❌ 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-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, без воды.