# 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`. ## Правка тела issue — только через API Тикнуть чекбокс в критериях приёмки нужно при закрытии каждой задачи, и `tea` для этого не годится. `tea issues edit --description` принимает тело **целиком строкой**, а взять эту строку неоткуда: `tea issues <номер>` печатает текст обёрнутым и разрисованным для терминала, обратно его не скормишь. Рабочий путь — забрать сырое тело из API, поправить и вернуть: ```sh # 1. сырой JSON тикета; тело — в поле body tea api repos/{owner}/{repo}/issues/ > issue.json # 2. правка тела любым удобным способом, например все чекбоксы разом python3 -c " import json d = json.load(open('issue.json')) json.dump({'body': d['body'].replace('- [ ]', '- [x]')}, open('patch.json', 'w'), ensure_ascii=False) " # 3. вернуть tea api -X PATCH -d @patch.json repos/{owner}/{repo}/issues/ ``` Флаги `tea api`: `-X` — метод, `-d` — сырое тело JSON (`@файл` читает из файла, `@-` из потока ввода), `-f` и `-F` — отдельные поля строкой и с типом. Флага `--input` нет, хотя рука тянется написать именно его. Тот же приём — для чек-листа родительской карты: пункт `- [ ] #NN` тикается правкой её тела, автоматически Gitea этого не делает. Комментарий правится тем же способом, но путь у него свой — без номера issue: `tea api -X PATCH -d @patch.json repos/{owner}/{repo}/issues/comments/`. Идентификатор берётся из `GET .../issues//comments`; это не порядковый номер комментария в ленте. Нужно это чаще, чем кажется: резолюции wayfinder-тикетов живут комментариями, и правка после ревью идёт в них. **Отсюда общее правило.** `tea` удобен там, где команда создаёт объект или меняет его свойство: создать issue, добавить комментарий, повесить метку, назначить исполнителя, закрыть. Как только нужно **изменить уже написанный текст** — тело issue, тело PR, — CLI мешает: он умеет только заменить всё целиком, а прочитать это «всё» в пригодном для правки виде не даёт. Такие операции идут прямо в API. ## Слияние PR не закрывает issue Gitea понимает только английские ключевые слова автозакрытия: `closes`, `fixes`, `resolves` (`Closes #13`). Русское «Закрывает #13» в теле PR — обычная ссылка, issue останется открытым. Наступали не раз: последний случай — слияние PR #17, где issue #13 пришлось закрывать руками. Отсюда простое правило: пиши в теле PR английское `Closes #NN` — тогда слияние закроет задачу само, и ручного шага не остаётся. Всё остальное в PR по-прежнему на русском: ключевое слово здесь не текст, а команда трекеру. Если ключевого слова не было, порядок после слияния: закрыть задачу (`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-08-13: правка комментария через `repos/{owner}/{repo}/issues/comments/` снята живыми запросами при закрытии #72 — так дважды правилась резолюция тикета. 2026-08-06: правка тела issue через `tea api -X PATCH -d @файл` снята живыми запросами при закрытии #37 — так проставлены чекбоксы самого тикета и пункт в чек-листе карты #4. Тогда же проверено, что `tea issues edit --description` для этого непригоден, а флага `--input` у `tea api` нет. 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 один в один.