Files
agents/GO-002-plan.md
T
2026-10-02 23:43:38 +07:00

165 lines
8.1 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.
# План GO-002: разорвать зависимости modules от repos и services
## Цель
Технические modules не импортируют прикладные `services` и storage `repos`.
Модуль получает собственные входные типы, а преобразование repository-моделей
делается на границе service.
Не меняем:
- protobuf/API и сгенерированные файлы;
- формат `scenario.json`, ZIP-архива и публичные ответы;
- бизнес-правила и SQL;
- `internal/modules/storytelling`, пока он не импортирует repos/services;
- GO-006 (`*_utils`) и GO-003 (единый error mapping).
## Фактические нарушения
| Module | Нарушение | Callers |
| --- | --- | --- |
| `modules/game_model` | импортирует `repos` и `services/scenarios_service` | game, gameplay, answer, team, MCP, app |
| `modules/scenario_archive` | `Pack` принимает `*repos.Scenario` | `scenarios_service`, module tests |
| `modules/scenario_archive` | импортирует `repos` только для storage-модели | только archive implementation |
## Правило миграции
Каждый кусок заканчивается рабочим компилятором и targeted-тестами. После
каждого шага проверять запрещённые импорты:
```sh
cd evening_detective_server
rg -n '"evening_detective_server/internal/(repos|services)' internal/modules --glob '*.go' --glob '!*_test.go'
go test ./internal/modules/... ./internal/services/...
```
## Маленькие этапы
### GO-002.0 — зафиксировать baseline
1. Сохранить список runtime-файлов с нарушениями:
`modules/game_model/game.go`, `game_mapper.go`, `team_mapper.go` и
`modules/scenario_archive/interface.go`/`archive.go`.
2. Проверить чистое состояние тестов:
```sh
GOCACHE=/tmp/evening-detective-go-cache go test ./internal/modules/... ./internal/services/...
```
3. Не менять callers и не создавать `common`, `domain` или `utils` только для
обхода импортов.
Готово, если baseline проходит и список зависимостей зафиксирован.
### GO-002.1 — выделить собственный входной тип archive module
Файлы: `internal/modules/scenario_archive/interface.go`, `archive.go` и
`archive_test.go`.
1. Добавить в module небольшой тип входа для упаковки архива, содержащий только
нужные поля: `Name`, `Description`, `Image` и сериализованную `Story`.
2. Изменить `IScenarioArchive.Pack` так, чтобы он принимал этот тип, а не
`*repos.Scenario`.
3. В implementation заменить обращения к `scenario.Scenario`,
`scenario.Description` и другим полям на поля нового типа.
4. Перевести module tests на новый тип. Формат `ScenarioJSON` не менять.
Проверка:
```sh
cd evening_detective_server
find internal/modules/scenario_archive -name '*.go' -print0 | xargs -0 gofmt -w
go test ./internal/modules/scenario_archive
! rg 'internal/repos' internal/modules/scenario_archive --glob '*.go'
```
Ожидаемый результат: archive module полностью независим от storage package.
### GO-002.2 — сделать mapping repository → archive в scenarios service
Файлы: `internal/services/scenarios_service/service.go`, mapper и тесты.
1. В `scenarios_service` собрать новый archive input из уже полученного
`*repos.Scenario`.
2. Передавать его в `scenarioArchive.Pack`; repository-зависимость остаётся
только в service, где ей место.
3. Не переносить в module права, запросы, storage и protobuf.
4. Сохранить поведение изображений, `nil`-описания и ссылок на story.
5. Добавить/обновить один round-trip тест `DownloadArchive` → `UploadArchive`.
Проверка:
```sh
cd evening_detective_server
go test ./internal/services/scenarios_service ./internal/modules/scenario_archive
! rg 'internal/repos' internal/modules/scenario_archive --glob '*.go'
```
### GO-002.3 — отделить game model от modules
Файлы: текущий `internal/modules/game_model/*` и callers.
1. Переместить типы `Game` и `Team` в пакет с той же предметной ответственностью
под `internal/services/game_model`.
2. Сохранить имена типов и поля, чтобы это была механическая смена import path,
а не новая модель или DTO.
3. Перенести вместе с типами текущие `MapGame`, `MapGames`, `MapTeam`,
`MapTeams`; они являются преобразованием storage-моделей в use-case-модели.
4. Обновить callers в `game_service`, `gameplay_service`, `answer_service`,
`team_service`, `mcp_service`, app и тестах.
5. Не делать пакет `common` и не дублировать структуры.
Проверка после механического переноса:
```sh
cd evening_detective_server
find internal/services/game_model internal/services/game_service internal/services/gameplay_service internal/services/answer_service internal/services/team_service internal/services/mcp_service internal/app -name '*.go' -print0 | xargs -0 gofmt -w
go test ./internal/services/game_model ./internal/services/game_service ./internal/services/gameplay_service ./internal/services/answer_service ./internal/services/team_service ./internal/services/mcp_service ./internal/app
! rg 'internal/modules/game_model' --glob '*.go'
```
### GO-002.4 — удалить старый module game_model
1. После успешного переноса убедиться, что `internal/modules/game_model` больше
не импортируется и не нужен через тесты.
2. Удалить только старые файлы package; новые копии не оставлять параллельно.
3. Проверить `go list ./...`, чтобы не осталось пустого/дублирующего пакета.
Проверка:
```sh
cd evening_detective_server
go list ./...
go test ./...
! test -d internal/modules/game_model
```
### GO-002.5 — финальная проверка направления зависимостей
1. Runtime modules не импортируют `internal/repos`, `internal/services` или
`internal/app`.
2. `scenario_archive` принимает только собственные типы и callbacks; SQL,
права и storage остаются снаружи.
3. `cmd` по-прежнему собирает concrete repositories/modules/services.
4. Проверить, что сценарный архив и game/team responses побайтно/структурно не
изменились в существующих тестах.
5. Запустить финальный gate:
```sh
cd evening_detective_server
find internal -type f -name '*.go' -print0 | xargs -0 gofmt -l
go vet ./...
go test ./...
```
6. Только после успешного полного gate отметить GO-002 как `DONE` в `todo.md`.
## Критерий готовности GO-002
- `rg 'internal/(repos|services)' internal/modules --glob '*.go' --glob '!*_test.go'` не находит runtime-импортов.
- Нет дубликатов `Game`, `Team` или archive input model.
- Все callers используют один пакет `services/game_model`.
- ZIP/`scenario.json`, game/team responses и существующие error semantics не
изменились.
- `gofmt`, `go vet ./...` и `go test ./...` проходят.