Логирование рабочего дня по данным из git
Учёт времени — из тех дел, которые делаются в шесть вечера по памяти и плохо. При этом свидетельства того, чем я на самом деле занимался, уже есть: коммиты, pull request'ы, события в календаре. Поэтому я написал агентский скилл, который их читает и заносит день в 7pace Timetracker — инструмент, которым пользуется наша организация в Azure DevOps. Вот как он устроен и какие правила сделали его надёжным.
Пайплайн
- Собрать свидетельства. Коммиты и pull request'ы за день из Azure DevOps (через
azCLI, потому что его--queryвозвращает только те поля, которые попросишь), встречи — из опубликованной ленты календаря. - Собрать план. Встречи стоят на своих календарных местах; рабочие блоки заполняют промежутки и привязываются к work item'ам, стоящим за коммитами. Шаг в полчаса, обычный день — восемь-девять часов, один тип активности на блок.
- Показать таблицей. Интервал, work item, часы, активность, комментарий.
- Дождаться явного «отправляй». Ничего не записывается, пока я не скажу, а правки возвращают к шагу 2.
- Записать и проверить. Записи уходят через MCP-сервер 7pace или, если на машине его нет, через Node-скрипт без зависимостей, который делает те же вызовы.
Жёсткие правила
В файле скилла несколько правил простым языком, и они работают лучше любого объёма кода:
- Worklog'и одного дня никогда не пересекаются. Записи идут строго одна за другой.
- Никогда не записывать без подтверждения.
- Никогда не логировать в будущее. В текущий день ни один блок не может заканчиваться позже «сейчас».
- У внутренних встреч нет work item. Встречи миссии идут на эпик этой миссии.
- Никогда не печатать и не коммитить токен.
Правило о пересечениях дополнительно проверяет скрипт: он просто отказывается от плана с наложениями. Правило, которое читает модель, и проверка, которую делает код, не дублируют друг друга: первое предотвращает большинство ошибок, второе ловит остальные.
Чему пришлось научить инструмент
Исходный MCP-сервер не мог залогировать ни одной записи на нашем инстансе. Типы активности приходили в форме, которую он не разбирал, поэтому он отправлял worklog'и без типа, и API их отклонял; эвристика превращала 15-минутные записи в 15-часовые; эндпоинт списка игнорировал фильтры по датам. Я сделал форк и починил это, а потом добавил две вещи, которые пайплайну действительно были нужны: необязательное время начала, чтобы записи можно было выкладывать последовательно, и необязательный work item, потому что у встреч его нет. Правило «без пересечений» ушло в описание инструмента — туда, где модель читает его перед вызовом.
Что я сказал бы тому, кто строит то же самое
- Кладите правила туда, где модель увидит их в момент решения: в описание инструмента и в скилл, а не в README.
- Пусть инструмент падает громко. Неизвестный тип активности должен показать список допустимых, а не молча выбросить поле и оставить API отвечать невнятным 400.
- Держите шлюз подтверждения на каждой записи. Читать свидетельства бесплатно; писать worklog'и — нет.
- Секреты не в репозитории:
.env.exampleв репо,.envв ignore, и проверка в скрипте, которая отказывается работать с токеном-заглушкой.
В итоге — несколько минут в день вместо восстановленной догадки и журнал, который совпадает с тем, что, по словам репозитория, происходило.