Files
PTSRaiAgent/docs/dev/WORKFLOW.md
ElebobaandClaude Opus 5.5 b4731fb1d6
CI / ruff · pytest (pull_request) Successful in 22s
chore(core): stage 1 contracts — dialog, API schemas + fixtures, integrations, monitoring, modules
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>
2026-10-03 15:22:25 +03:00

132 lines
8.1 KiB
Markdown
Raw Permalink 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.
# Регламент работы: зоны, задачи, 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`](GITEA_API.md)).
- Тело issue — по шаблону [`ISSUE_TEMPLATE.md`](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
```markdown
## Что меняется
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)
1. **В LLM — только `scrub()`-текст.** Прямой вызов клиента GigaChat в обход `app/llm/gateway.py` запрещён.
2. **Safety до LLM.** При `acute` LLM не вызывается вообще.
3. **Алерты и скоринг детерминированы** — LLM не решает (ADR-007).
4. **Время — только из `app.core.clock`** (ADR-005).
5. **identity ↔ clinical — только через токен.** Модули clinical не импортируют `app.db.identity`.
6. **Доступ врача → `audit_log`.**
7. **Пороги, тексты и лексикон — в `config/`**, не в коде.
8. **Только синтетика.** Логи без ПДн и без сырого текста.
9. **Никаких зарубежных API в контуре.**
## Факапы
| Ситуация | Действие |
|---|---|
| Начал в основной копии | `git stash` → worktree → `git stash pop` |
| `git push` дал `[new branch]` после мержа | удалить ветку через API, новый issue + cherry-pick |
| Конфликт при rebase в чужой зоне | спросить владельца |
| Утёк секрет | отозвать ключ, вычистить историю |
| Битая кириллица в issue/PR | см. [`GITEA_API.md`](GITEA_API.md): только `--data-binary @файл` |