Freeze interfaces between lanes A (bot), B (backend), C (dashboard) so three developers work in parallel without touching each other's files: dialog Event/Reply + engine registry with echo stub, integration protocols with in-memory defaults, MonitoringService with noop stub, /api/v1 schemas with fixture-backed routes, frozen main.py wiring, config/modules.yaml + due_scales(), DAR-5, tzdata, Andrey trajectory, lanes in WORKFLOW, ADR-010. Refs #34 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.1 KiB
Регламент работы: зоны, задачи, git, коммиты
Основан на регламенте TenVex/vobot, облегчён под хакатон (ADR-009). Дедлайн: пн 05.10.2026, 13:00 МСК.
Зоны (lanes) и файлы
Три разработчика делят слои, а не направления (ADR-010): каждый ведёт свой слой для всех сценариев. У каждой зоны свои файлы — в чужие не заходим, поэтому коллизий нет.
| Lane | Кто | Владеет файлами | Метки зон |
|---|---|---|---|
| A — бот | Егор (Eleboba) |
app/dialog/**, app/channels/**, app/llm/**, config/texts/**, tests/test_dialog_*, tests/test_telegram*, tests/test_llm* |
bot, lane/A |
| B — backend | разработчик 2 | app/api/** (кроме schemas.py), app/services/** (кроме contracts.py), app/scheduler/**, app/integrations/** (кроме base.py), app/db/**, app/core/** (правки — мелким PR), scripts/**, data/**, tests/test_api*, tests/test_services*, tests/test_scheduler*, tests/test_seed*, tests/test_integrations*, tests/test_db* |
backend, core, lane/B |
| C — дашборд | разработчик 3 | dashboard/**, tests/test_dashboard* |
dashboard, lane/C |
| clinical | психиатр | значения в config/scales/*, config/rules.yaml, config/lexicon/*, вычитка config/texts/* |
clinical |
| pitch | медик | docs/pitch/** |
pitch |
Замороженные контракты (меняются только отдельным мелким PR [contract] с пингом всех трёх):
app/core/types.py, app/dialog/contracts.py, app/api/schemas.py, app/integrations/base.py, app/services/contracts.py, app/main.py, app/config.py, config/modules.yaml, config/rules.yaml (схема), pyproject.toml/uv.lock, docker-compose.yml, Makefile, .gitea/.
Как зоны стыкуются без ожидания друг друга:
- A → B: движок вызывает
get_monitoring().after_data_change()иintegrations.*. До готовности B это заглушки (NoopMonitoring,Memory*). - B → A: API и шедулер вызывают
get_engine().handle(). До готовности A этоEchoEngine. - C → B: дашборд ходит только в
/api/v1. До #12 ручки отдают фикстуры (app/api/fixtures.py). - Реальная реализация регистрируется сама:
register_engine()/register_monitoring()при импорте модуля,integrations.<field> = ...вapp/integrations/setup().
Направления развития
| Направление | Статус | Milestone |
|---|---|---|
| Ветераны СВО | фокус хакатона | Этап 1 · Ветераны СВО (+ M3 Сдача) |
| Семьи ветеранов | опционально, после хакатона | Будущее · Семьи ветеранов (эпик #40) |
| Депрессия в общей популяции | опционально, после хакатона | Будущее · Депрессия (общая популяция) (эпик #43) |
Новое направление = новый файл app/dialog/flows/<module>.py + запись в config/modules.yaml; движок, API и дашборд расширяются в своих зонах.
Откуда задачи
- Только из Gitea
$GITEA_REPO. Нет issue — нет кода. Нет подходящего issue — заведи его на себя. - Атрибуты: метка зоны +
lane/A|B|C, тип (feature/fix/refactor/docs/chore), размер (size/0.5≈ 2 ч,size/1≈ 4 ч,size/2≈ день), milestone (M1/M2/M3), приоритетP0/P1/P2. - Одна задача = одна зона. Нужно несколько зон → несколько issue, связанных зависимостью через API (
GITEA_API.md). - Тело issue — по шаблону
ISSUE_TEMPLATE.md.
Milestones
| Milestone | Срок | Смысл |
|---|---|---|
| M1 Каркас | сб 03.10 ✅ | ядро, БД, LLM-шлюз, конфиги |
| Этап 1 · Ветераны СВО | вс 04.10, 23:59 | демо Андрея end-to-end (эпик #35) |
| M3 Сдача | пн 05.10, 13:00 | README, презентация PDF, репетиция, dev → main |
| Будущее · … | без срока | опциональные направления |
Жизненный цикл задачи
1. Взял issue (assignee = $GITEA_USER), зона свободна
2. git fetch origin
3. git worktree add .claude/worktrees/<issue#>-<slug> -b <type>/<issue#>-<slug> origin/dev ← ДО первого изменения
4. cp .env в worktree; uv sync
5. Код по модулям; коммиты с Refs #N
6. git ls-remote --heads origin <ветка> ← пусто после первого пуша = PR смержен, стоп
7. git fetch && git rebase origin/dev
8. make lint && make test
9. Лог в тело issue: ### YYYY-MM-DD
10. PR в dev с Closes #N → после зелёного CI мержит автор (облегчение хакатона)
11. git worktree remove .claude/worktrees/<issue#>-<slug>
Задача завершена → сам: коммит → push → PR. Не запушено — не сделано.
Git
main ← сдаваемая версия, мержит только человек (пн утром)
dev ← интеграция, сюда все PR
<type>/<issue#>-<slug> ← от dev
Коммиты — Conventional Commits
feat(core): add PHQ-9 scoring with item-9 escalation
Refs #3
scope = зона. Closes #N — только в описании PR.
Шаблон PR
## Что меняется
1–3 предложения.
Closes #<N>
## Зона
A | B | C | clinical | pitch | docs | contract
## Как проверить
шаги/команды
## Чек-лист
- [ ] rebase на origin/dev
- [ ] make lint + make test зелёные
- [ ] лог в issue (### YYYY-MM-DD)
- [ ] нет ПДн в логах, нет реальных данных, нет секретов
- [ ] общие файлы (CLAUDE.md, docker-compose, pyproject) — отдельный мелкий PR с пингом
Guardrails (проверяются в каждом PR)
- В LLM — только
scrub()-текст. Прямой вызов клиента GigaChat в обходapp/llm/gateway.pyзапрещён. - Safety до LLM. При
acuteLLM не вызывается вообще. - Алерты и скоринг детерминированы — LLM не решает (ADR-007).
- Время — только из
app.core.clock(ADR-005). - identity ↔ clinical — только через токен. Модули clinical не импортируют
app.db.identity. - Доступ врача →
audit_log. - Пороги, тексты и лексикон — в
config/, не в коде. - Только синтетика. Логи без ПДн и без сырого текста.
- Никаких зарубежных API в контуре.
Факапы
| Ситуация | Действие |
|---|---|
| Начал в основной копии | git stash → worktree → git stash pop |
git push дал [new branch] после мержа |
удалить ветку через API, новый issue + cherry-pick |
| Конфликт при rebase в чужой зоне | спросить владельца |
| Утёк секрет | отозвать ключ, вычистить историю |
| Битая кириллица в issue/PR | см. GITEA_API.md: только --data-binary @файл |