Compare commits

...

2 Commits

Author SHA1 Message Date
VLADIMIR 49fbda9e09 updates 2026-08-30 21:40:50 +07:00
VLADIMIR ec2ea7d4a1 add rules 2026-08-30 21:25:02 +07:00
4 changed files with 116 additions and 12 deletions
+37
View File
@@ -0,0 +1,37 @@
# Правила работы в репозитории 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`;
- саморевью фактическими проверками до отправки сеньёру (поведение функций на реальных данных, сгенерированный код, арифметика).
## Улучшения вне скоупа (скилл todo-collect)
Если в ходе задачи нашлось улучшение/долг, не мешающее текущей работе — **не чини попутно**: запиши его в локальную папку `todo/` по скиллу `todo-collect` (каждая задача — отдельный файл, шаблон в скилле) и продолжай текущую задачу. Папка в `.gitignore` — это локальный журнал, не коммитится.
+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 раундов** замечания не исчерпались — остановись и спроси пользователя: продолжать цикл или зафиксировать оставшиеся замечания как известные ограничения.
## Критерии готовности ## Критерии готовности
+54
View File
@@ -0,0 +1,54 @@
---
name: todo-collect
description: Записывает найденные улучшения «вне скоупа» текущей задачи в локальную папку todo/ — каждую задачу в отдельный файл, без выполнения и без расширения scope. Загружай при работе над любой задачей (реализация, ревью, рефакторинг, исследование), чтобы не терять замечания, не мешающие текущей работе.
whenToUse: В процессе любой задачи обнаружено улучшение, оптимизация, потенциальный баг или долг, которые не блокируют и не относятся к текущей задаче. Триггеры: замечание в коде, «на будущее» из ревью, осознанное ограничение, отложенное решение.
---
# Сбор улучшений «вне скоупа» в todo/
## Контекст
В ходе задачи постоянно встречаются места, которые можно улучшить, но чинить их сейчас — значит расширять scope и рисковать текущей работой (правило «не отклоняйся молча»). Такие находки не должны теряться: они записываются в локальную папку `todo/` репозитория (в `.gitignore`, в git не попадает) — **каждая задача в свой отдельный файл**.
## Правила
1. **Записывай, не чини.** Нашёл улучшение, не мешающее текущей задаче — запиши в `todo/` и продолжай текущую работу. Не выполняй записанные задачи в текущей сессии, если пользователь явно об этом не попросил.
2. **Одна задача — один файл.** Имя файла — kebab-case, отражающее суть: `todo/<chto-i-gde>.md` (например, `todo/mapimage-idempotent-prefix.md`). Если файл с той же сутью уже существует — дополни его, не создавай дубль.
3. **Записывай сразу.** Не откладывай «на потом»: в конце задачи контекст уже потерян. Короткая запись по шаблону ниже занимает минуту.
4. **Фиксируй только факты и предложения.** Без воды: что не так, где, как исправить (с оценкой риска), кто/когда нашёл.
5. **Не перемещай и не удаляй чужие записи.** Менять статус/содержимое своей записи можно; чужие — только по договорённости.
6. **Папка локальная.** `todo/` в `.gitignore` — не коммить, не синхронизировать. Если задача заслуживает общего трекинга — предложи пользователю перенести её в issue-трекер.
## Шаблон записи
```markdown
# <Краткое название задачи>
- **Где найдено**: <файл/пакет/место в коде; в какой задаче>
- **Дата**: <YYYY-MM-DD>
- **Статус**: todo
## Проблема
<что именно не так, почему это проблема, при каких условиях проявится>
## Предложение
<как исправить, с указанием конкретных файлов/функций; оценка риска и объёма>
## Связи
<опционально: связанные todo-файлы, ссылки на код, замечания ревью>
```
## Статусы
- `todo` — записано, не начато;
- `in_progress` — кто-то взялся (укажи имя/сессию);
- `done` — выполнено (укажи, как и когда; можно удалить файл после подтверждения).
## Критерии готовности записи
- [ ] Проблема описана так, что понятна без контекста исходной задачи.
- [ ] Предложено конкретное исправление (или явно сказано, что решение открыто).
- [ ] Файл лежит в `todo/` с kebab-case именем, дублей нет.
+4
View File
@@ -31,6 +31,10 @@ go.sum
.gocache/ .gocache/
.gotmp/ .gotmp/
# Локальный журнал улучшений «вне скоупа» текущей задачи
# (каждая запись — отдельный файл, см. скилл todo-collect)
todo/
.VSCodeCounter/ .VSCodeCounter/
docker-compose-prod.yml docker-compose-prod.yml