add rules

This commit is contained in:
2026-08-30 21:25:02 +07:00
parent c0b5ceb65f
commit ec2ea7d4a1
2 changed files with 54 additions and 12 deletions
+33
View File
@@ -0,0 +1,33 @@
# Правила работы в репозитории evening_detective_server
Дополняют глобальный `~/.dsh/AGENTS.md`. Применяются в любой сессии в этом каталоге.
## Сборка и проверки
- **Кэш сборки**: системный `GOCACHE` (`/home/vladimir/.cache/go-build`) в этом окружении read-only. Всегда запускай Go-команды с локальным кэшем:
`export GOCACHE=/home/vladimir/projects/evening_detective_server/.gocache`
(иначе `go build/vet/test` падают с `read-only file system`).
- Стандартный набор проверок после изменений: `gofmt -l cmd/ internal/ api/`, `go build ./...`, `go vet ./...`, `go test -count=1 ./...`; при конкурентности — `go test -race ./...`.
- `go mod tidy` может не отработать (read-only module cache): если не хватает только перевода импортируемого пакета в прямые зависимости — перенеси его в первый require-блок вручную (эквивалентно tidy).
## Прото
- API описано в `api/main.proto`; сгенерированный код — `proto/` и `cmd/evening_detective_server/main.swagger.json`.
- После правки proto обязателен `make generate` (protoc v35.1, плагины в `~/go/bin`), затем `go build ./...`.
- **Конвенция REST — camelCase** (`accessToken`, `actionsCount`). Осознанное исключение: `file_type` в `Application`/`UploadFileRsp` (явный `json_name = "file_type"`, единый snake_case с внутренним JSON истории). Новые поля с явным json_name — только по согласованию.
## Известные факты (не переоткрывать в каждой задаче)
- Файлы хранятся в S3-совместимом RustFS (`file_storage`), URL префиксуются `FILE_PREFIX_DOMAIN` (см. `.env.example`). В БД и JSON истории — относительные имена; префикс добавляется только при чтении (идемпотентно, `prefixDomain`/`mapStory`).
- `string_tools.Transliterate` удаляет ВСЁ кроме `[a-z0-9_]` — включая точку расширения: `Transliterate("photo.png")``"photopng"`. Работать с расширением файла — отдельно (split base/ext до транслитерации).
- Улики = `Application { name, image, file_type }` (proto `api/main.proto`, `storytelling.Application`): живут в JSON истории сценария и в таблице `applications` (выданные команде). `file_type`: `image | pdf | audio`, деривируется из расширения через `file_storage.FileType`.
- Загрузка файлов: `POST /api/files/upload` — только роль `Author`, allowlist расширений pdf/jpg/jpeg/png/gif/webp/mp3/ogg/wav, содержимое проверяется sniff'ом (текст/html отклоняется), имя уникализируется `translit(base)_<hex>.<ext>`. Лимит файла 64 МБ: HTTP `maxFileUploadBody`, gRPC `grpcMsgLimit = maxFileSize + 1MiB`, бизнес-проверка в `file_service`.
- Ошибки размера на HTTP-слое мапятся в 413 через `customErrorHandler` (см. `cmd/evening_detective_server/main.go`): ветка `InvalidArgument` + «request body too large» — единственная реальная защита 413 (сгенерированный gateway-код строкифицирует `*http.MaxBytesError` через `%v`).
- Скачивание `GET /api/files/{filename}` — публичное, с `X-Content-Type-Options: nosniff`.
## Процесс ревью (скилл task-execution)
Загружай скилл `task-execution` для нетривиальных задач. Внутри него действуют правила экономии контекста:
- бюджет **3 раунда** на цикл (план/результат), «все замечания одним списком»;
- план/состояние — во внешнем файле (`.dsh/task-plan.md`), промпт ревью — дельта + `git diff`;
- саморевью фактическими проверками до отправки сеньёру (поведение функций на реальных данных, сгенерированный код, арифметика).
+21 -12
View File
@@ -13,7 +13,7 @@ whenToUse: Пользователь просит выполнить задачу
## Роли ## Роли
- **Исполнитель** — ты (агент). Составляешь план, выполняешь, правишь по замечаниям. - **Исполнитель** — ты (агент). Составляешь план, выполняешь, правишь по замечаниям.
- **Сеньёр (senior developer)** — отдельный субагент, запускаемый через `subagent`. Он **не видит наш диалог**, поэтому каждый промпт ревью должен быть самодостаточным: включай в него всю необходимую информацию (задачу, план, критерии, предыдущие замечания). - **Сеньёр (senior developer)** — отдельный субагент, запускаемый через `subagent`. Он **не видит наш диалог**, поэтому каждый промпт ревью должен быть самодостаточным — но самодостаточность достигается за счёт внешнего файла состояния, а не дублирования всего плана в промпте (см. правило 9).
- **Пользователь** — источник требований и финальный судья. Ему задаются вопросы при неясностях. - **Пользователь** — источник требований и финальный судья. Ему задаются вопросы при неясностях.
## Обязательные правила ## Обязательные правила
@@ -25,6 +25,9 @@ whenToUse: Пользователь просит выполнить задачу
5. **Неясно — спроси.** На любом этапе (задача, шаг плана, замечание сеньёра) при неоднозначности задай вопрос пользователю через `ask_user_question`. Догадки вместо вопросов — ошибка. 5. **Неясно — спроси.** На любом этапе (задача, шаг плана, замечание сеньёра) при неоднозначности задай вопрос пользователю через `ask_user_question`. Догадки вместо вопросов — ошибка.
6. **Отслеживай прогресс** через `todo_write`: план из шага 2 переносится в todo-список, пункты отмечаются по мере выполнения. 6. **Отслеживай прогресс** через `todo_write`: план из шага 2 переносится в todo-список, пункты отмечаются по мере выполнения.
7. **Профильные скилы** (например `create-go-module`) — источник правил «как делать» для конкретной задачи. Этот скил управляет процессом «как вести задачу»; оба применяются вместе. 7. **Профильные скилы** (например `create-go-module`) — источник правил «как делать» для конкретной задачи. Этот скил управляет процессом «как вести задачу»; оба применяются вместе.
8. **Бюджет раундов ревью — 3 на цикл** (план и результат отдельно). В шаблонах промптов требуй от сеньёра перечислить **все замечания одним списком за один заход** — включая мелочи, ниты и потенциальные будущие проблемы. После 3 раундов без `APPROVED` остановись и спроси пользователя: продолжать цикл или зафиксировать оставшиеся замечания как известные ограничения (не растягивай полировку на десятки раундов).
9. **Дифф-ревью и внешнее состояние.** План, чек-лист и учёт замечаний держи во внешнем файле состояния (например, `.dsh/task-plan.md`). Промпт ревью содержит: задачу, путь к файлу состояния, **короткую дельту** «что изменилось с прошлого раза» и `git diff` изменённых файлов. Не пересказывай ревьюеру весь план и всю историю замечаний — файл состояния он прочитает сам (это его контекст, а не наш).
10. **Саморевью до отправки.** Перед первым и каждым повторным ревью прогоняй фактические проверки, которые сеньёр всё равно сделает: поведение функций на реальных данных (например, `Transliterate("photo.png")`, `http.DetectContentType`, `filepath.Ext("x.PNG?v=2")`), чтение сгенерированного кода (pb.gw.go и пр.), арифметику лимитов. «Ревью результата» отправляй как `git diff` + выводы проверок, а не как пересказ плана.
## Шаги ## Шаги
@@ -46,12 +49,12 @@ whenToUse: Пользователь просит выполнить задачу
### 3. Ревью плана сеньёром ### 3. Ревью плана сеньёром
Запусти субагента с промптом по шаблону **«Ревью плана»** (ниже). Сеньёр возвращает либо `APPROVED`, либо список замечаний. Сохрани план и критерии в файл состояния (например, `.dsh/task-plan.md`), прогони саморевью (правило 10), затем запусти субагента с промптом по шаблону **«Ревью плана»** (ниже). Сеньёр возвращает либо `APPROVED`, либо список замечаний.
### 4. Цикл правок плана ### 4. Цикл правок плана
- Есть замечания → исправь план (и todo-список), отправь на ревью **повторно**: в промпт добавь предыдущие замечания и что именно изменилось. - Есть замечания → исправь план в файле состояния (и todo-список), отправь на ревью **повторно**: в промпт добавь только дельту «что изменилось с прошлого раза» (правило 9).
- Повторяй, пока не получишь `APPROVED`. - Повторяй, пока не получишь `APPROVED`; после 3 раундов без `APPROVED` — спроси пользователя (см. «Ограничение итераций»).
### 5. Выполнение ### 5. Выполнение
@@ -59,11 +62,11 @@ whenToUse: Пользователь просит выполнить задачу
### 6. Ревью результата ### 6. Ревью результата
Сначала сам проверь результат (прогони проверки из плана), затем отдай его сеньёру по шаблону **«Ревью результата»**. Сеньёр сверяет результат с планом и критериями, проверяет корректность и соблюдение конвенций проекта. Сначала сам проверь результат (прогони проверки из плана, правило 10), затем отдай его сеньёру по шаблону **«Ревью результата»**: `git diff` изменённых файлов + выводы проверок. Сеньёр сверяет результат с планом (файл состояния) и критериями, проверяет корректность и соблюдение конвенций проекта.
### 7. Цикл правок результата ### 7. Цикл правок результата
Правь по замечаниям, повторяй ревью, пока сеньёр не вернёт `APPROVED`. При каждом повторе сообщай сеньёру, что изменилось с прошлого раза. Правь по замечаниям, повторяй ревью, пока сеньёр не вернёт `APPROVED`. При каждом повторе сообщай сеньёру только дельту — что изменилось с прошлого раза (правило 9). После 3 раундов без `APPROVED` — спроси пользователя.
### 8. Финальный отчёт ### 8. Финальный отчёт
@@ -71,15 +74,19 @@ whenToUse: Пользователь просит выполнить задачу
## Шаблон: промпт «Ревью плана» ## Шаблон: промпт «Ревью плана»
План и критерии — в файле состояния (путь ниже); в промпт включай только задачу, путь к файлу, дельту с прошлого раза (если есть) и diff, если правился код.
``` ```
Ты — senior developer. Оцени план выполнения задачи. Ты — senior developer. Оцени план выполнения задачи.
Задача: <текст задачи> Задача: <текст задачи>
План: <план> План и критерии готовности: <путь к файлу состояния, например .dsh/task-plan.md> (прочитай сам)
Критерии готовности: <критерии> Изменения с прошлого раза: <дельту или «первое ревью»>
Проверь: полноту (нет ли пропущенных шагов), достижимость, корректность Проверь: полноту (нет ли пропущенных шагов), достижимость, корректность
подхода, риски, соответствие конвенциям проекта, отсутствие лишних шагов. подхода, риски, соответствие конвенциям проекта, отсутствие лишних шагов.
Перечисли ВСЕ замечания одним списком за один заход — включая мелочи,
ниты и потенциальные будущие проблемы; не растягивай на несколько раундов.
Ответь СТРОГО одним из двух вариантов: Ответь СТРОГО одним из двух вариантов:
- APPROVED — если замечаний нет; - APPROVED — если замечаний нет;
- список замечаний, каждое в формате «<что не так> → <как исправить>». - список замечаний, каждое в формате «<что не так> → <как исправить>».
@@ -91,12 +98,14 @@ whenToUse: Пользователь просит выполнить задачу
Ты — senior developer. Оцени результат выполнения задачи. Ты — senior developer. Оцени результат выполнения задачи.
Задача: <текст задачи> Задача: <текст задачи>
План: <план> План и критерии готовности: <путь к файлу состояния> (прочитай сам)
Критерии готовности: <критерии> Результат: git diff изменённых файлов + выводы проверок (build/vet/test/race)
Результат: <что сделано: файлы, изменения, выводы проверок> Изменения с прошлого раза: <дельту или «первое ревью»>
Проверь: результат соответствует плану и критериям готовности, код/текст Проверь: результат соответствует плану и критериям готовности, код/текст
корректен, соблюдены конвенции проекта, нет регрессий. корректен, соблюдены конвенции проекта, нет регрессий.
Перечисли ВСЕ замечания одним списком за один заход — включая мелочи,
ниты и потенциальные будущие проблемы.
Ответь СТРОГО одним из двух вариантов: Ответь СТРОГО одним из двух вариантов:
- APPROVED — если замечаний нет; - APPROVED — если замечаний нет;
- список замечаний, каждое в формате «<что не так> → <как исправить>». - список замечаний, каждое в формате «<что не так> → <как исправить>».
@@ -104,7 +113,7 @@ whenToUse: Пользователь просит выполнить задачу
## Ограничение итераций ## Ограничение итераций
Если в одном цикле (план или результат) после **5 раундов** замечания не исчерпались — остановись и спроси пользователя: продолжать цикл или зафиксировать оставшиеся замечания как известные ограничения. Если в одном цикле (план или результат) после **3 раундов** замечания не исчерпались — остановись и спроси пользователя: продолжать цикл или зафиксировать оставшиеся замечания как известные ограничения.
## Критерии готовности ## Критерии готовности