8.0 KiB
8.0 KiB
agent-v15-sprints — решения агента
Спека и дизайн изменения — в sdlc-hub/openspec/changes/sprints-backlog/ (issue aep/sdlc-hub#108, aep/jira-agent#49).
Агентская часть: требование agent «Спринты, ранг и оценки» (ADDED); контракт команд — commands «Команда —
желаемый результат на одной задаче» (MODIFIED: story_points в ensure_fields, ensure_sprint_meta,
ensure_sprint_state, ensure_rank) и абзацы о командах спринтов; формат состояния — hub-api «Приём досок и
спринтов» (ADDED). Версия агента — 15.
Решения агента
- Поля Jira — по типу поля, один раз на процесс.
GET /rest/api/2/fieldпри первой нужде, кэш на процесс:- ранг — поле с
schema.custom = "com.pyxis.greenhopper.jira:gh-lexo-rank"; - спринт — поле с
schema.custom = "com.pyxis.greenhopper.jira:gh-sprint"; - story points — поле с именем «Story Points» (без учёта регистра); несколько — первое по id.
Перекрытие из настроек хаба:
field_ids.rank,field_ids.sprint,field_ids.story_points(если заданы — поиск не нужен). ОшибкаGET /field— поля считаются ненайденными, причина в лог; повтор — в следующемrefresh.
- ранг — поле с
sprint_ids— из поля спринта в том жеsearch, а не обходом спринтов: id поля спринта добавляется вfieldsпоиска. Значение — список; элемент — объект сid(Jira 8+) или строкаcom.atlassian.greenhopper.service.sprint.Sprint@…[id=72,…](Jira Server): id — изidили изid=<n>в строке; не разобралось — элемент пропускается с записью в лог. Поля нет —sprint_idsне передаётся (хаб сохранит прежнее). Имя текущего спринта (sprint) — как в v12 (обход активных и будущих спринтов досок), без изменений.rank,story_points— тоже изsearch: id полей добавляются вfields.story_points— число (intилиfloat), иное —null; поле не найдено —story_pointsне передаётся у задач и запись в лог один раз.- Данные досок. Для каждой доски
scrum/kanbanизrefresh.boards(тип известный или только что определённый):- колонки —
GET /rest/agile/1.0/board/{id}/configuration→columnConfig.columns[]{name, statuses: [{id}]}; id статусов переводятся в имена поGET /rest/api/2/status(кэш на процесс; неизвестный id — пропускается); - kanban-бэклог (только
kanban):GET /rest/agile/1.0/board/{id}/backlog?maxResults=0— 200 →true, 400 →false, иное →null; проверить на Jira банка при выкатке; - спринты (только
scrum):GET /rest/agile/1.0/board/{id}/sprintбез фильтра состояния, постранично (50); элемент →{id, name, state, start_date: startDate, end_date: endDate, complete_date: completeDate, goal}; - ошибка чтения настроек доски —
columns: null,kanban_backlog: null, спринты — если прочитались; причина в лог.boardsприкладывается к первой пачкеPOST /agent/state; при пустой выборке — одна пачка{issues: [], links: [], boards}. Доски без данных (типnull) вboardsне входят.
- колонки —
- Даты команд спринта.
start_date/end_date(ГГГГ-ММ-ДД) →ГГГГ-ММ-ДДT09:00:00.000<смещение>иГГГГ-ММ-ДДT18:00:00.000<смещение>, смещение — локального времени агента (time.strftime("%z"), вид+0300). Сравнение с Jira — по дате (первые 10 символовstartDate/endDate). ensure_sprint_meta. Спринты доскиboard_id— все состояния (тот же обход, что в п. 4, кэш на команду); поиск по имениsprint(точное совпадение). Нет —POST /rest/agile/1.0/sprint{name: rename_to or sprint, originBoardId, startDate?, endDate?, goal?}; есть —POST /rest/agile/1.0/sprint/{id}только с отличающимися полями (nameприrename_to, даты по п. 5,goal); нет отличий —doneбез записи. Ошибки — по контрактуcommands.ensure_sprint_state.active: спринтfuture—POST /sprint/{id}{state: "active", startDate, endDate}(из спринта; нет дат —failed).closed: колонки доски (п. 4) → набор статусов последней колонки; задачи спринта (GET /sprint/{id}/issue?fields=status, постранично) не в этих статусах — вmove_open_to(POST /sprint/{to}/issueилиPOST /backlog/issue, по 50 ключей), затемPOST /sprint/{id}{state: "closed"}. Колонки не прочитались —failed«не удалось прочитать колонки доски». Между записями — зазор типа команды, как вensure_link.ensure_rank. Ранг обеих задач —searchпоkey in (key, other)с полем ранга; нет поля ранга —failed«поле ранга не найдено»; уже выше/ниже (сравнение строк) —done {changed: false}; иначеPUT /rest/agile/1.0/issue/rank{issues: [key], rankBeforeIssue | rankAfterIssue: other, rankCustomFieldId}→{changed: true}.story_pointsвensure_fields. Поле по п. 1; не найдено —failed«поле оценки не найдено в Jira: задайте field_ids.story_points». Сравнение чисел: равны, еслиabs(a - b) < 1e-9;null— очистка (NoneвPUT).
Decisions made without discussion
| Маркер | Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|---|
| R-60 | 2026-10-24 | Поля ранга, спринта, оценки — по типу/имени через GET /field, перекрытие field_ids (п. 1) |
Владелец полей не знает, оценок в AURORA ещё нет | Не то поле «Story Points» — задать field_ids.story_points |
| R-61 | 2026-10-24 | sprint_ids из поля спринта в search, разбор строкового вида Jira Server (п. 2) |
Обход закрытых спринтов — N запросов на спринт; поле есть у каждой задачи | Формат поля банка иной — sprint_ids пропадут, видно на живой проверке |
| R-62 | 2026-10-24 | Kanban-бэклог — по ответу GET /board/{id}/backlog (п. 4) |
В configuration Jira Server явного признака нет |
null — у kanban нет раздела «Бэклог» |
| R-63 | 2026-10-24 | Время дат спринта — 09:00 и 18:00 по локальному времени агента (п. 5) | Команда несёт только дату | Другое время в Jira — правка спринта руками |