diff --git a/AGENTS.md b/AGENTS.md index 36c3748..c419220 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,8 +48,7 @@ Airflow) и названия из кода. Если для понятия ес Трекер — Gitea на `git.dementev.space`, работа через CLI `tea` (логин по умолчанию настроен, репозиторий определяется по git remote). Команды и -подводные камни описаны в -[доке предшественника](https://git.dementev.space/ddmitry/clickstream-ch-kafka-superset-demo/src/branch/main/docs/agents/issue-tracker.md). +подводные камни — в [`docs/agents/issue-tracker.md`](docs/agents/issue-tracker.md). - Спека фичи — файл в `docs/specs/`, источник истины, версионируется с кодом. - Корневой issue фичи — тонкий: ссылка на спеку и чек-лист дочерних issues @@ -60,8 +59,33 @@ Airflow) и названия из кода. Если для понятия ес - Метки триажа — пять ролей: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. Карта и её тикеты — метки `wayfinder:*`. +## Agent skills + +### Issue tracker + +Задачи — в Gitea на `git.dementev.space`, все операции через CLI `tea`. +См. [`docs/agents/issue-tracker.md`](docs/agents/issue-tracker.md). + +### Triage labels + +Пять канонических меток триажа без переименований, уже заведены в трекере. +См. [`docs/agents/triage-labels.md`](docs/agents/triage-labels.md). + +### Domain docs + +Один контекст: `CONTEXT.md` в корне и `docs/adr/`. +См. [`docs/agents/domain.md`](docs/agents/domain.md). + ## Структура - Новые документы — в `docs/` или в профильных подпапках, не в корне. - Состав доков v2 определяется по ходу этапов, набор предшественника не копируется (спека, раздел 12). +- Имена файлов в `docs/specs/` и `docs/research/` — `ГГГГ-ММ-ДД-краткое-имя.md`: + дата создания документа и слаг строчными латинскими буквами через дефис + (`2026-07-30-stand-v2-realism.md`). Дата фиксирует, когда документ появился, + и при правках не меняется: файлы сортируются по времени, а история живёт + в git. +- Имена файлов в `docs/adr/` — `NNNN-краткое-имя.md`: сквозной номер из четырёх + цифр и слаг (`0001-stand-services.md`). Решения нумеруются подряд, дата + в имени не нужна. diff --git a/docs/agents/domain.md b/docs/agents/domain.md new file mode 100644 index 0000000..fe22ec3 --- /dev/null +++ b/docs/agents/domain.md @@ -0,0 +1,54 @@ +# Доки предметной области + +Как скиллам читать документацию репозитория, прежде чем лезть в код. + +## Что прочитать до разбора кода + +- **`CONTEXT.md`** в корне — словарь понятий проекта. +- **`docs/adr/`** — решения. Читать те ADR, что касаются области, в которой + сейчас работаешь. +- **`docs/specs/`** — спеки фич; для этого репозитория спека и есть источник + истины по тому, что строим (см. `docs/agents/issue-tracker.md`). + +Если файла нет — **просто идти дальше молча**. Не сообщать об отсутствии и не +предлагать создать заранее. Скилл `/domain-modeling` (через `/grill-with-docs` +и `/improve-codebase-architecture`) заводит их лениво, когда термин или решение +действительно понадобилось зафиксировать. + +## Разметка: один контекст + +Репозиторий одноконтекстный — один `CONTEXT.md` в корне и один `docs/adr/`: + +``` +/ +├── CONTEXT.md ← пока не создан, появится по надобности +├── docs/ +│ ├── adr/ ← 0001-stand-services.md +│ ├── specs/ +│ └── research/ +├── dags/ +├── infra/ +└── scripts/ +``` + +Карта контекстов (`CONTEXT-MAP.md` в корне и по `CONTEXT.md` на контекст) — +для больших многопакетных репозиториев; здесь она не нужна. Если репозиторий +когда-нибудь разъедется на несколько контекстов, разметку менять здесь. + +## Пользоваться словарём + +Если в выводе называешь понятие предметной области (заголовок issue, гипотеза, +имя теста, предложение по рефакторингу) — бери термин ровно в том виде, как он +записан в `CONTEXT.md`. Не уходить в синонимы, от которых словарь отказался. + +Понятия нет в словаре — это сигнал: либо выдумываешь язык, которого в проекте +нет (стоит передумать), либо нашёл настоящий пробел (отметить для +`/domain-modeling`). + +## Спорить с ADR вслух + +Если то, что ты предлагаешь, противоречит принятому ADR — сказать об этом прямо, +а не переехать решение молча: + +> _Противоречит ADR-0001 (состав сервисов стенда) — но открыть заново стоит, +> потому что…_ diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md new file mode 100644 index 0000000..5296c87 --- /dev/null +++ b/docs/agents/issue-tracker.md @@ -0,0 +1,132 @@ +# Issue tracker: Gitea + +Задачи этого репозитория живут в Gitea на `git.dementev.space` +(`ddmitry/clickstream-data-platform`, это remote `origin`). Все операции — +через CLI [`tea`](https://gitea.com/gitea/tea), официальный клиент Gitea; по +устройству он близок к `gh` и `glab`. Логин и репозиторий `tea` определяет сам +по git remote в текущем каталоге. + +## Перед первым запуском + +- **Бинарник.** Скачивается с `https://dl.gitea.com/tea/<версия>/` (файл + `tea-<версия>-linux-amd64` и `.sha256` рядом), кладётся в `~/.local/bin/tea`. + Проверка: `tea --version`. +- **Вход.** `tea logins add --name git.dementev.space --url + https://git.dementev.space`, токен передаётся переменной + `GITEA_SERVER_TOKEN` (не аргументом командной строки — он попадёт в историю + оболочки). Логин уже добавлен и назначен по умолчанию, так что `tea` работает + из любого каталога. +- **Скоупы токена:** `read:user` (без него `tea` откажется добавлять логин), + `write:issue`, `write:repository`. Токен выпускается в UI: Settings → + Applications. Нехватка скоупа выглядит не как «нет прав», а как невнятная + ошибка или пустой ответ. +- **Прокси.** Домен `dementev.space` должен быть в `NO_PROXY`, иначе запросы + уходят в прокси и виснут. В обычной оболочке это делает `proxy-client` из + `~/dotfiles`. Если переменная не подхватилась, короткий разовый префикс: + `NO_PROXY='*' tea ...`. + +## Команды + +- **Создать issue:** `tea issues create --title "..." --description "..."`. + Многострочное тело удобнее собрать heredoc'ом в переменную и подставить + как `--description "$BODY"`. +- **Прочитать issue:** `tea issues <номер> --comments`. +- **Список:** `tea issues list --state open --output json --fields + index,title,labels,assignees`. Фильтры: `--labels`, `--assignee`, + `--keyword`. +- **Комментарий:** `tea comments add <номер> -d "..."`. +- **Метки:** `tea issues edit <номер> --add-labels "..."` / `--remove-labels + "..."`. Список меток репозитория — `tea labels list`, создать новую — + `tea labels create --name "..." --color "..."`. +- **Закрыть:** `tea issues close <номер>`. Комментария при закрытии команда не + принимает — сначала `tea comments add`, потом `close`. +- **Взять в работу:** `tea issues edit <номер> --add-assignees ddmitry`. + Сокращения вида `@me` в `tea` нет, имя пишется целиком. +- **Чего нет в CLI** — через `tea api `: команда ходит в REST API Gitea + уже с сохранённым токеном, например + `tea api repos/ddmitry/clickstream-data-platform/issues/18`. + +## Слияние PR не закрывает issue + +Gitea понимает только английские ключевые слова автозакрытия: `closes`, +`fixes`, `resolves` (`Closes #13`). Русское «Закрывает #13» в теле PR — обычная +ссылка, issue останется открытым. Наступали не раз: последний случай — слияние +PR #17, где issue #13 пришлось закрывать руками. + +Порядок после слияния: закрыть задачу (`tea issues close <номер>`) и тикнуть +её пункт в чек-листе родительского issue этапа — Gitea чек-листы сама не +обновляет. + +## Спека — источник истины + +- Спецификация фичи — файл в `docs/specs/`, версионируется с кодом. +- Корневой issue фичи — **тонкий**: ссылка на спеку + чек-лист дочерних issues + (`- [ ] #NN`). Содержание спеки в issue не дублируется — истина одна, в git. +- Дочерние issues — полноценные самодостаточные постановки: цель, критерии + приёмки чекбоксами, границы («что трогать нельзя»), «сначала прочитать», + команды проверки. +- Итоговые резолюции и решения — в спеку или ADR тем же PR; issue — рабочая + переписка, она не обязана переживать фичу. + +## Когда скилл говорит «опубликовать в issue tracker» + +Создать issue в Gitea: `tea issues create ...`. + +## Когда скилл говорит «достать тикет» + +`tea issues <номер> --comments`. + +## PR как поверхность триажа + +**Нет** — одиночный учебный репозиторий, внешних PR не ждём. (Если включить — +`/triage` начнёт гонять PR через те же метки и состояния командами +`tea pulls ...`.) + +## Wayfinding-операции + +Используются `/wayfinder`. Карта — один issue, тикеты — дочерние issues. + +- **Карта**: issue с меткой `wayfinder:map` (Notes / Decisions-so-far / Fog + в теле). +- **Дочерний тикет**: вложенных issues в Gitea нет, поэтому связь держится + двумя ссылками — пункт списка `- [ ] #NN` в теле карты и строка + `Part of #<карта>` в начале тела тикета. Метки: `wayfinder:<тип>` + (`research` / `prototype` / `grilling` / `task`). +- **Блокировки**: нативные зависимости Gitea — единственный источник истины, + текстовых строк `Blocked by:` в телах тикетов нет. В CLI их команд нет, + работаем через `tea api` (`{owner}` и `{repo}` подставляются из текущего + репозитория): + - добавить блокер: `tea api repos/{owner}/{repo}/issues//dependencies + -F index=<блокер> -f owner=ddmitry -f repo=clickstream-data-platform` + — поля `owner` и `repo` обязательны, без них API отвечает + «repository does not exist»; + - кто блокирует тикет: `GET .../issues//dependencies`; + - кого блокирует тикет: `GET .../issues//blocks`; + - снять блокировку: тот же путь методом `DELETE` с тем же телом. + + Тикет разблокирован, когда у всех блокеров `state == "closed"`. +- **Фронтир**: открытые дети карты минус заблокированные и назначенные; первый + в порядке карты. Блокеры проверяются запросом `dependencies` по каждому + кандидату. +- **Взять в работу**: `tea issues edit --add-assignees ddmitry` — первая + запись за сессию. +- **Закрыть**: `tea comments add -d "<ответ>"`, затем `tea issues close + `, затем указатель на контекст (суть + ссылка) в Decisions-so-far карты. + +## Что проверено и когда + +2026-07-31: Gitea 1.27.0 (`tea api version`), `tea` 0.15.0. Живыми запросами по +этому репозиторию проверены `tea labels list` и `tea issues list`. Остальной +набор команд, флагов и приёмы с `tea api` перенесены из доки +предшественника — там они снимались с `tea <команда> --help` установленного +бинарника и проверялись живыми запросами 2026-07-29. При обновлении `tea` стоит +перечитать `--help`: набор флагов между версиями менялся. + +## Архив + +- Трекер предшественника — репозиторий + [`ddmitry/clickstream-ch-kafka-superset-demo`](https://git.dementev.space/ddmitry/clickstream-ch-kafka-superset-demo). + Задачи оттуда сюда не переносились: платформа v2 начата с чистого трекера. +- До 2026-07-26 задачи предшественника жили в GitHub Issues + (`dementev-dev/…`); аккаунт заблокирован, номера воссозданы в Gitea один + в один. diff --git a/docs/agents/triage-labels.md b/docs/agents/triage-labels.md new file mode 100644 index 0000000..2af78cd --- /dev/null +++ b/docs/agents/triage-labels.md @@ -0,0 +1,22 @@ +# Метки триажа + +Скиллы говорят о пяти канонических ролях триажа. Эта таблица переводит роли в +метки, которые реально заведены в трекере репозитория. + +| Роль в скиллах | Метка у нас | Значение | +| ----------------- | ----------------- | ------------------------------------------- | +| `needs-triage` | `needs-triage` | Задачу надо оценить, решение не принято | +| `needs-info` | `needs-info` | Ждём уточнений от автора | +| `ready-for-agent` | `ready-for-agent` | Постановка полная, можно отдавать агенту | +| `ready-for-human` | `ready-for-human` | Нужен человек | +| `wontfix` | `wontfix` | Делать не будем | + +Имена совпадают с каноническими: переименований нет. Когда скилл говорит про +роль («поставь метку готовности для агента»), берём строку из правой колонки. + +Все пять меток уже созданы в Gitea (проверено `tea labels list` 2026-07-31) — +заводить их заново не нужно. Кроме них в репозитории живут метки карты +`wayfinder:*` (`map`, `research`, `prototype`, `grilling`, `task`); к триажу они +отношения не имеют, ими размечает `/wayfinder`. + +Если вокабуляр меток поменяется — править правую колонку здесь, а не в скиллах.