Оценка через доску: board_id в ensure_fields со story_points (#113) #120
2
openspec/changes/sp-estimation-board/.openspec.yaml
Normal file
2
openspec/changes/sp-estimation-board/.openspec.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-10-25
|
||||
49
openspec/changes/sp-estimation-board/design.md
Normal file
49
openspec/changes/sp-estimation-board/design.md
Normal file
@ -0,0 +1,49 @@
|
||||
## Context
|
||||
|
||||
Основа — `main` `af70ba8` (после sprints-backlog #108, схема v9, агент v15). Issue #113, ветка
|
||||
`feat/113-sp-estimation-board`. Агент — jira-agent#53, ветка `feat/53-v16-sp-estimation`, design-only change
|
||||
`agent-v16-sp-estimation`.
|
||||
|
||||
Что есть сейчас:
|
||||
- агент v15 пишет `story_points` в `PUT /rest/api/2/issue/{key}` вместе с остальными полями (`do_ensure_fields`);
|
||||
- Jira банка 25.10.2026 отклонила запись: поле оценки не на экране редактирования;
|
||||
- хаб дописывает `board_id` только в `ensure_sprint` (по проекту задачи, `hooks._assign_boards`) и в команды спринта
|
||||
(по проекту пакета, `hooks._assign_project_board`); `retry_params` снимает его у этих типов;
|
||||
- живые данные: доска 4216 (`AWPCA`, scrum), поле оценки доски `customfield_15852` = `field_ids.story_points` хаба.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:** оценки из чата ставятся в Jira банка; повтор без изменений — без записи; контракт `ensure_fields` для
|
||||
остальных полей не меняется.
|
||||
|
||||
**Non-Goals:** см. proposal.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Оценка — через ресурс оценки доски** `/rest/agile/1.0/issue/{key}/estimation?boardId=…` (владелец, 25.10.2026:
|
||||
«давай» на предложенную схему после проверки ресурса в браузере). Так ставит оценку бэклог Scrum; экран
|
||||
редактирования не нужен.
|
||||
2. **Доска — по проекту задачи, как у `ensure_sprint`** (владелец, 25.10.2026). Те же 422; текст для канбана —
|
||||
свой: «у проекта P канбан-доска, оценка — только на scrum-доске»; задача вне проектов — «… доску для оценки не
|
||||
определить».
|
||||
3. **`board_id` только при `story_points` в параметрах.** `ensure_fields` без оценки проверок доски не проходит — задачи
|
||||
вне проектов правятся, как раньше.
|
||||
4. **Повтор (`command_retry`) снимает `board_id` у `ensure_fields`** — доска определяется заново, как у `ensure_sprint`.
|
||||
5. **Подтверждение по зеркалу не меняется:** `story_points` в зеркале — то же поле `customfield_15852`.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Формат `value` в `PUT …/estimation`.** Документация Atlassian показывает строку (`"8.5"`), Jira отдаёт число
|
||||
(`1.0`). Агент шлёт число; если Jira банка не примет — правка агента после живой проверки на одной задаче (до пакета).
|
||||
- **Частичная запись.** Остальные поля `PUT /issue` пишутся до оценки; ошибка оценки — `failed`, повтор команды
|
||||
остальные поля не меняет (уже совпадают).
|
||||
|
||||
## Decisions made without discussion
|
||||
|
||||
| Дата | Решение | Обоснование | Цена ошибки |
|
||||
|---|---|---|---|
|
||||
| 25.10.2026 | R-1. Без `board_id` в команде агент v16 ставит оценку через `PUT /issue`, как v15 | совместимость с хабом до этого change; агент выкатывается после хаба, но порядок не гарантирован | нет: без доски поведение то же, что сейчас |
|
||||
| 25.10.2026 | R-2. Порядок в агенте: сначала `PUT /issue` с остальными полями, затем оценка | оценка — новый путь с риском ошибки; остальные поля не должны зависеть от неё | частичная запись при ошибке оценки — повтор безопасен |
|
||||
| 25.10.2026 | R-3. `GET /issue` не делается, если в команде только оценка | пакет оценок — 64 команды; минус один вызов Jira на команду | нет |
|
||||
| 25.10.2026 | R-4. Текст 422 для канбана у `ensure_fields` — отдельный | «спринтов нет» вводит в заблуждение для оценки | косметика |
|
||||
| 25.10.2026 | R-5. `value` в `PUT …/estimation` — число (`null` — очистить) | Jira отдаёт значение числом; проверяется вживую до пакета | одна правка агента |
|
||||
33
openspec/changes/sp-estimation-board/proposal.md
Normal file
33
openspec/changes/sp-estimation-board/proposal.md
Normal file
@ -0,0 +1,33 @@
|
||||
## Why
|
||||
|
||||
25.10.2026 первый пакет оценок (64 команды `ensure_fields` со `story_points` из сессии awp-ca) остановился на первой же
|
||||
команде: Jira банка отвечает на `PUT /rest/api/2/issue/{key}` «Field cannot be set. It is not on the appropriate screen,
|
||||
or unknown». Поле оценки `customfield_15852` («Story point estimate») верное, но его нет на экране редактирования:
|
||||
в Jira оценку можно поставить только из бэклога Scrum. Владелец проверил в браузере: в Jira банка есть
|
||||
`GET /rest/agile/1.0/issue/AURORA-1704/estimation?boardId=4216` → `{"fieldId":"customfield_15852","value":1.0}`, а у доски
|
||||
4216 в настройках `estimation.field.fieldId = customfield_15852`. Этот же ресурс принимает `PUT` и пишет оценку в поле
|
||||
доски без проверки экрана.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Команды:** `ensure_fields` со `story_points` получает `board_id` доски проекта задачи — хаб дописывает при
|
||||
постановке по тем же правилам, что у `ensure_sprint` (422: задача вне проектов, разные доски, нет доски, канбан, тип
|
||||
не известен); от клиента `board_id` — 422; `command_retry` снимает `board_id` и определяет доску заново.
|
||||
- **Агент v16** (design-only change `agent-v16-sp-estimation` в jira-agent, issue jira-agent#53): оценка из
|
||||
`ensure_fields` с `board_id` — через `GET`/`PUT /rest/agile/1.0/issue/{key}/estimation?boardId=…`; остальные поля —
|
||||
как раньше; без `board_id` — как v15.
|
||||
- **MCP:** описание `batch_create` сообщает, что `board_id` у `ensure_fields` со `story_points` хаб дописывает сам.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Оценки на канбан-досках: команда отклоняется при постановке (решение владельца 25.10.2026; канбан-проектов с оценками пока нет).
|
||||
- Чтение оценки в `refresh` через доску: поле `field_ids.story_points = customfield_15852` верное, чтение не меняется.
|
||||
- Схема зеркала, API чтения, веб — не меняются.
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/sdlc_hub/modules/jira/hooks.py` (`_assign_boards`, `retry_params`), `src/sdlc_hub/modules/jira/mcp.py` (описание
|
||||
`batch_create`), тесты `tests/test_api.py`, `tests/test_commands.py`/`tests/test_mcp.py`.
|
||||
- Агент: `jira-agent/src/agent.py` (`do_ensure_fields`, `AGENT_VERSION = 16`).
|
||||
- Выкатка: хаб (pull, kickstart, `/mcp` reconnect) → `agent publish` v16 → живая проверка оценки одной задачи →
|
||||
`min_agent_version = 16` → пакет оценок заново.
|
||||
46
openspec/changes/sp-estimation-board/specs/agent/spec.md
Normal file
46
openspec/changes/sp-estimation-board/specs/agent/spec.md
Normal file
@ -0,0 +1,46 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Спринты, ранг и оценки
|
||||
Агент v15 SHALL в каждом `refresh` (по JQL и по ключам) для каждой доски из `boards` команды с типом `scrum` или
|
||||
`kanban` (известным или только что определённым) прочитать настройки доски (`GET /rest/agile/1.0/board/{id}/configuration`:
|
||||
колонки и их статусы — по именам статусов; признак kanban-бэклога, если Jira его отдаёт, иначе `null`) и, у `scrum`,
|
||||
все спринты доски любого состояния (`GET /rest/agile/1.0/board/{id}/sprint` постранично) и приложить к первой пачке
|
||||
состояния `boards` (см. `hub-api`, «Приём досок и спринтов»). Ошибка чтения настроек доски — доска с `columns: null`,
|
||||
`kanban_backlog: null`; ошибка чтения списка спринтов scrum-доски — доска в `boards` не входит (хаб сохраняет прежние
|
||||
данные), имена спринтов задач — по правилам v12; причина в лог; `refresh` продолжается.
|
||||
|
||||
Каждая задача в состоянии (с v15) SHALL нести `rank` — значение поля ранга Jira (поле типа LexoRank), `story_points` —
|
||||
значение поля оценки (`field_ids.story_points`, если задано, иначе поле Jira с именем «Story Points»), и `sprint_ids` —
|
||||
id всех спринтов задачи из поля спринта Jira (любого состояния). Поле не найдено — ключ у задач не передаётся (хаб
|
||||
сохраняет прежнее значение) и запись в лог один раз за `refresh`.
|
||||
|
||||
Агент v15 SHALL выполнять `ensure_sprint_meta`, `ensure_sprint_state`, `ensure_rank` и `story_points` в
|
||||
`ensure_fields` по контракту `commands`; сравнение — до записи, повтор без изменений — `done` без записи.
|
||||
|
||||
Агент v16 SHALL ставить `story_points` из `ensure_fields` с `board_id` через оценку доски, а не через `PUT /issue`: поле
|
||||
оценки может не быть на экране редактирования, и Jira отвечает «Field cannot be set. It is not on the appropriate screen,
|
||||
or unknown» (Jira банка, 25.10.2026), а бэклог Scrum ставит оценку и без экрана. Текущее значение —
|
||||
`GET /rest/agile/1.0/issue/{key}/estimation?boardId=<board_id>` (`{fieldId, value}`); отличается — `PUT` туда же с
|
||||
`{"value": …}` (`null` — очистить); сравнение — как у v15 (`3` равно `3.0`, `null` — только `null`). `field_ids.story_points`
|
||||
для записи с доской не нужен. `GET /issue` и `PUT /issue` агент делает только для остальных полей команды; в `changed` —
|
||||
`story_points`, если оценка записана. Команда без `board_id` — оценка через `PUT /issue`, как v15. Ошибка Jira на
|
||||
`estimation` — `failed` с текстом Jira; остальные поля к этому моменту уже записаны (повтор их не меняет).
|
||||
|
||||
#### Scenario: Доска с закрытыми спринтами
|
||||
- **WHEN** `refresh {jql: …, boards: [{id: 4216, type: "scrum"}]}`, у доски закрытые спринты 1–2, активный 3, будущий 4
|
||||
- **THEN** первая пачка состояния несёт `boards` с доской 4216, четырьмя спринтами и колонками; у задачи спринта 2,
|
||||
перенесённой в 3, — `sprint_ids: [2, 3]`
|
||||
|
||||
#### Scenario: Нет поля оценки
|
||||
- **WHEN** в Jira нет поля «Story Points», `field_ids.story_points` не задан
|
||||
- **THEN** у задач нет ключа `story_points`; `ensure_fields {key: X, story_points: 3}` — `failed` «поле оценки не найдено
|
||||
в Jira: задайте field_ids.story_points»
|
||||
|
||||
#### Scenario: Оценка не на экране редактирования
|
||||
- **WHEN** агент v16, `ensure_fields {key: AURORA-1704, story_points: 2, board_id: 4216}`, оценка в Jira — `1.0`
|
||||
- **THEN** `GET /rest/agile/1.0/issue/AURORA-1704/estimation?boardId=4216`, затем `PUT` туда же `{"value": 2}`; `PUT /issue`
|
||||
нет; отчёт `done` с `changed: ["story_points"]`, `jira_calls = 2`
|
||||
|
||||
#### Scenario: Оценка уже стоит
|
||||
- **WHEN** та же команда, оценка в Jira — `2.0`
|
||||
- **THEN** только `GET …/estimation`; отчёт `done` с `changed: []`, `jira_calls = 1`
|
||||
118
openspec/changes/sp-estimation-board/specs/commands/spec.md
Normal file
118
openspec/changes/sp-estimation-board/specs/commands/spec.md
Normal file
@ -0,0 +1,118 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Команда — желаемый результат на одной задаче
|
||||
Каждая команда SHALL описывать желаемое состояние одной задачи Jira и выполняться агентом как «прочитать → сравнить →
|
||||
записать только разницу». Повторное выполнение любой команды с тем же результатом в Jira SHALL завершаться `done`
|
||||
без записи. `fetch_attachment` в Jira не пишет: она читает файл вложения и передаёт его хабу; повтор безопасен. Типы команд и их контракт:
|
||||
|
||||
| Тип | Параметры | Что читает | Что пишет |
|
||||
|---|---|---|---|
|
||||
| `ensure_issue` | `temp_key` (`new:<n>`), `issue_type` (`task`/`epic`/`bug`), `summary`, `description`, `priority`, `duedate`, `planned_start`, `planned_end`, `labels`, `epic_key`, `assignee` | поиск `project = <proj> AND reporter = currentUser() AND created >= -7d`, точное сравнение `summary` | при отсутствии — `POST /issue` с типом из `issue_types.<issue_type>` (для эпика — с `epic_name_field_id`); результат `key` |
|
||||
| `ensure_fields` | `key`, любое подмножество: `summary`, `description`, `priority`, `duedate`, `planned_start`, `planned_end`, `labels_add`, `labels_remove`, `epic_key`, `assignee`, `story_points` (число ≥ 0 или `null` — очистить); при `story_points` `board_id` хаб дописывает при постановке (от клиента — 422) | `GET /issue/{key}` — если есть поля, кроме оценки; оценка — `GET /rest/agile/1.0/issue/{key}/estimation?boardId=<board_id>` | `PUT /issue/{key}` только с отличающимися полями, кроме оценки; эпик — по `epic_link.mode`; оценка отличается — `PUT /rest/agile/1.0/issue/{key}/estimation?boardId=<board_id>` с `{value}` (поле оценки доски, экран редактирования Jira не нужен); команда без `board_id` — оценка через `PUT /issue/{key}` в поле story points, как в v15 (см. `agent`, «Спринты, ранг и оценки») |
|
||||
| `ensure_comment` | `key`, `marker`, `body` | `GET /issue/{key}/comment` | комментарий с `marker` в начале: `PUT` если текст отличается, `POST` если нет |
|
||||
| `ensure_status` | `key`, `target` (имя статуса или список-путь) | `GET /issue/{key}` (статус), `GET /issue/{key}/transitions` на каждом шаге | `POST /transitions` по шагам пути; при отсутствии перехода — `failed` с перечнем доступных |
|
||||
| `ensure_link` | `source`, `target`, `link_type` (логическое имя из `link_types`), `replace` (bool) | `GET /issue/{source}` (`issuelinks`) | нет нужной и нет конфликта — `POST /issueLink`; конфликт (другой тип из `link_types` или обратное направление) и `replace` — `DELETE` лишней, затем `POST`; конфликт без `replace` — `failed` с описанием |
|
||||
| `ensure_sprint` | `key`, `sprint` (имя или `backlog`); `board_id` хаб дописывает при постановке (от клиента — 422) | `GET /issue/{key}` (поле спринта), список спринтов доски `board_id` (активные и будущие) | `POST /rest/agile/1.0/sprint/{id}/issue` или `POST /rest/agile/1.0/backlog/issue` |
|
||||
| `ensure_sprint_meta` | `sprint` (имя), необязательные `rename_to`, `start_date`, `end_date` (`ГГГГ-ММ-ДД`), `goal`; `board_id` хаб дописывает при постановке (от клиента — 422) | спринты доски `board_id` (все состояния) | спринта с именем `sprint` нет — `POST /rest/agile/1.0/sprint` (`originBoardId`, имя `rename_to` или `sprint`, даты, цель); есть — `POST /rest/agile/1.0/sprint/{id}` только с отличающимися полями; спринт закрыт — `failed` «спринт закрыт»; результат `{sprint_id, created}` |
|
||||
| `ensure_sprint_state` | `sprint`, `state` (`active` или `closed`), `move_open_to` (имя активного или будущего спринта той же доски или `backlog`; при `closed` обязателен, при `active` — 422); `board_id` — как у `ensure_sprint_meta` | спринты доски (все состояния), задачи спринта и колонки доски | `active`: спринт будущий — `POST /sprint/{id}` `state = active` (нет дат у спринта — `failed` «у спринта нет дат: задайте ensure_sprint_meta»); `closed`: задачи спринта не в последней колонке доски — в `move_open_to`, затем `state = closed`; уже в нужном состоянии — ничего; результат `{sprint_id, moved: [ключ…]}` |
|
||||
| `ensure_rank` | `key` и ровно одно из `before`, `after` (ключ другой задачи) | ранг обеих задач | `key` уже выше `before` (ниже `after`) — ничего; иначе `PUT /rest/agile/1.0/issue/rank` (`rankBeforeIssue` / `rankAfterIssue`) |
|
||||
| `ensure_attachment` | `key`, `file` (sha256 файла в хранилище хаба, 64 hex-символа), `filename` (имя вложения в Jira, без `/`, `\`, `"` и управляющих символов); `size` хаб дописывает при выдаче | `GET /issue/{key}?fields=attachment` | вложения с тем же `filename` и размером нет — файл у хаба (`GET /agent/files/{file}`), затем `POST /issue/{key}/attachments` (multipart); есть — ничего; результат `attachment_id` |
|
||||
| `refresh` | `keys` (список) или `jql`; `boards` (`[{id, type}]` — доски проектов, `type` — `scrum`, `kanban` или `null`) хаб дописывает при выдаче | `search` с полями зеркала, по 100 на страницу; плюс дочитывание соседей по `issuelinks`; доски с неизвестным типом — `GET /rest/agile/1.0/board/{id}` | ничего в Jira; состояние уходит в хаб; результат — `boards: {"<id>": "scrum" | "kanban" | null}` для досок, чей тип агент запрашивал |
|
||||
| `fetch_attachment` | `key`, `attachment_id` (id вложения Jira, строка из цифр) | `GET /issue/{key}?fields=attachment` (имя и размер вложения) | ничего в Jira; содержимое — `GET <base_url>/secure/attachment/{id}/{имя}`, затем хабу `POST /agent/files`; результат `{attachment_id, file, size}` |
|
||||
|
||||
Доску для `ensure_sprint` и для `ensure_fields` с `story_points` хаб SHALL определять при постановке: проект задачи — проекты, чьи метки есть у задачи в
|
||||
зеркале (для временного ключа — в `labels` её `ensure_issue` в пакете, после дописывания метки проекта); `board_id` —
|
||||
доска этого проекта. 422 при постановке: задача ни в одном проекте; в нескольких проектах с разными досками; у проекта
|
||||
нет доски; тип доски `kanban` («у проекта P канбан-доска, спринтов нет»; у `ensure_fields` — «у проекта P канбан-доска, оценка — только на scrum-доске»); тип доски ещё не известен («тип доски проекта P
|
||||
ещё не известен — дождитесь обновления из Jira»). `boards` у `refresh` хаб SHALL дописывать при каждой выдаче (в базе
|
||||
не хранится): все доски проектов без повторов. По результату `refresh` хаб SHALL записать присланные типы `scrum` и
|
||||
`kanban` в проекты с этой доской; `null` тип не меняет.
|
||||
|
||||
Доску для `ensure_sprint_meta` и `ensure_sprint_state` хаб SHALL определять при постановке по проекту пакета
|
||||
(`project` пакета): пакет без проекта — 422 «команды спринта — только в пакете проекта»; у проекта нет доски, доска
|
||||
`kanban` или тип ещё не известен — 422 с теми же текстами, что у `ensure_sprint`. `ensure_rank` в пакете проекта
|
||||
принадлежит проекту по `key`; `before`/`after` — любая задача. Повтор команды (`command_retry`) SHALL снимать `board_id`
|
||||
у `ensure_sprint_meta`, `ensure_sprint_state` и `ensure_fields`, как у `ensure_sprint`: доска определяется заново. Хвостовой `refresh` пишущего пакета с
|
||||
`ensure_sprint_meta` или `ensure_sprint_state` SHALL быть `refresh {jql: <JQL проекта пакета>}` (`project =
|
||||
<project_key> AND labels in ("<метка>")`); иначе — как раньше, по ключам команд. Подтверждения по состоянию зеркала у
|
||||
`ensure_sprint_meta`, `ensure_sprint_state`, `ensure_rank` нет.
|
||||
|
||||
`ensure_sprint_meta` SHALL искать спринт по имени среди всех спринтов доски: закрытый — `failed` «спринт закрыт»;
|
||||
несколько с этим именем — `failed` «несколько спринтов с именем …: <id…>»; `rename_to` на имя другого спринта доски —
|
||||
`failed` «имя занято». `ensure_sprint_state`: `closed` для будущего спринта — `failed` «спринт не начат»; `active` для
|
||||
закрытого — `failed` «спринт закрыт»; результат `ensure_rank` — `{changed}`.
|
||||
|
||||
Семантика `ensure_link`: `source` блокирует/ссылается на `target`; агент в `POST /issueLink` SHALL ставить `source` в
|
||||
`inwardIssue`, `target` в `outwardIssue` (проверено на Jira банка 11.10.2026).
|
||||
|
||||
Текст описания (`ensure_fields`) и тело комментария (`ensure_comment`) агент SHALL сравнивать с текущим значением в Jira
|
||||
без различия переводов строк `\r\n` и `\n`; записывается текст команды как есть. Jira хранит присланный текст, а правленный
|
||||
в веб-интерфейсе — с `\r\n` (проверено на Jira банка 13.10.2026).
|
||||
|
||||
#### Scenario: Повтор уже выполненной команды
|
||||
- **WHEN** `ensure_fields {key: AURORA-1533, duedate: 2026-10-23}` выполняется, а в Jira срок уже 23.10
|
||||
- **THEN** агент не делает `PUT`, отчёт `done`, `jira_calls = 1`
|
||||
|
||||
#### Scenario: Описание отличается только переводами строк
|
||||
- **WHEN** `ensure_fields {key: X, description: "а\nб"}`, а в Jira описание X — `"а\r\nб"`
|
||||
- **THEN** агент не делает `PUT`, отчёт `done` с `changed = []`
|
||||
|
||||
#### Scenario: Замена связи
|
||||
- **WHEN** `ensure_link {source: AURORA-1537, target: AURORA-1538, link_type: "связанные", replace: true}` и в Jira между
|
||||
ними «блокирует начало» 1537→1538
|
||||
- **THEN** `DELETE` старой связи, пауза по политике, `POST` новой; отчёт `done` с обеими операциями
|
||||
|
||||
#### Scenario: Связь-конфликт без replace
|
||||
- **WHEN** та же команда с `replace: false`
|
||||
- **THEN** `failed`, в `error` найденная связь, Jira не изменена
|
||||
|
||||
#### Scenario: Переход по пути
|
||||
- **WHEN** `ensure_status {key: X, target: ["Разработка", "Готово"]}` и X в «Ожидание разработки»
|
||||
- **THEN** два `POST /transitions` с паузой между ними; если X уже «Готово» — `done` без записи
|
||||
|
||||
#### Scenario: Создание ошибки
|
||||
- **WHEN** `ensure_issue {temp_key: new:1, issue_type: bug, summary: "ОСВ 60 не распознана", labels: [AWPCA]}`, в настройках
|
||||
`issue_types.bug = {name: "Ошибка"}` без `id`
|
||||
- **THEN** агент создаёт задачу с `issuetype = {name: "Ошибка"}`; отчёт `done` с ключом
|
||||
|
||||
#### Scenario: Вложение уже есть
|
||||
- **WHEN** `ensure_attachment {key: X, file: <sha>, filename: "ОСВ 60.xlsx"}`, у X в Jira есть вложение «ОСВ 60.xlsx» того
|
||||
же размера
|
||||
- **THEN** агент не скачивает файл у хаба и не загружает его в Jira; отчёт `done` с `attachment_id` найденного, `jira_calls = 1`
|
||||
|
||||
#### Scenario: Вложение с тем же именем, другого размера
|
||||
- **WHEN** та же команда, у X есть «ОСВ 60.xlsx» другого размера
|
||||
- **THEN** агент загружает файл вторым вложением с тем же именем (Jira это допускает); отчёт `done` с новым `attachment_id`
|
||||
|
||||
#### Scenario: Создание с проверкой дубля
|
||||
- **WHEN** `ensure_issue` повторяется после падения агента, а задача с той же темой от нас уже создана час назад
|
||||
- **THEN** агент не создаёт вторую, отчёт `done` с ключом найденной
|
||||
|
||||
#### Scenario: Спринт задачи проекта
|
||||
- **WHEN** у AURORA-1538 метка `AWPCA`, проект `AWPCA` с доской 4216 типа `scrum`; `ensure_sprint {key: AURORA-1538, sprint: "Спринт 2"}`
|
||||
- **THEN** пакет создан, в параметрах команды `board_id = 4216`
|
||||
|
||||
#### Scenario: Спринт на канбане
|
||||
- **WHEN** у AURORA-1 метка `STOCKS_DRRK`, доска проекта — `kanban`; `ensure_sprint {key: AURORA-1, sprint: "Спринт 2"}`
|
||||
- **THEN** 422 «у проекта STOCKS_DRRK канбан-доска, спринтов нет»
|
||||
|
||||
#### Scenario: Тип доски определён
|
||||
- **WHEN** проект `STOCKS_DRRK` с доской 5120 и `board_type = null`; выдаётся `refresh`, агент вернул `boards: {"5120": "kanban"}`
|
||||
- **THEN** при выдаче в параметрах `boards` есть `{id: 5120, type: null}`; после отчёта у проекта `board_type = kanban`
|
||||
|
||||
#### Scenario: Оценка задачи проекта
|
||||
- **WHEN** у AURORA-1692 метка `AWPCA`, доска проекта 4216 типа `scrum`; `ensure_fields {key: AURORA-1692, story_points: 1}`
|
||||
- **THEN** пакет создан, в параметрах команды `board_id = 4216`; агент читает и пишет оценку через
|
||||
`/rest/agile/1.0/issue/AURORA-1692/estimation?boardId=4216`, `PUT /issue` не делает
|
||||
|
||||
#### Scenario: Поля без оценки — без доски
|
||||
- **WHEN** `ensure_fields {key: AURORA-1, duedate: 2026-10-30}`, задача вне проектов
|
||||
- **THEN** пакет создан, `board_id` в параметрах нет
|
||||
|
||||
#### Scenario: Оценка задачи вне проектов
|
||||
- **WHEN** `ensure_fields {key: AURORA-1, story_points: 2}`, у AURORA-1 нет меток проектов
|
||||
- **THEN** 422 «команда 1: AURORA-1 не входит ни в один проект — доску для оценки не определить»
|
||||
|
||||
#### Scenario: Оценка на канбане
|
||||
- **WHEN** у AURORA-1 метка `STOCKS_DRRK`, доска проекта — `kanban`; `ensure_fields {key: AURORA-1, story_points: 2}`
|
||||
- **THEN** 422 «команда 1: у проекта STOCKS_DRRK канбан-доска, оценка — только на scrum-доске»
|
||||
22
openspec/changes/sp-estimation-board/specs/mcp/spec.md
Normal file
22
openspec/changes/sp-estimation-board/specs/mcp/spec.md
Normal file
@ -0,0 +1,22 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Спринты и бэклог в MCP
|
||||
MCP `sdlc-jira` SHALL давать инструменты чтения по `GET /agile` проекта сессии (сессия без проекта — тот же отказ, что у
|
||||
прочих инструментов с проектом):
|
||||
- `sprints` — таблица спринтов доски: имя, состояние, даты, задач (выполнено/всего), SP (выполнено/всего), без оценки;
|
||||
закрытые — 10 последних и строка «ещё N закрытых», если их больше; без доски — «у проекта нет доски»;
|
||||
- `sprint` (`name`, по умолчанию — активный) — шапка спринта (имя, состояние, даты, цель, суммы) и задачи по колонкам
|
||||
доски: ключ, тема (до 80 символов), исполнитель, SP;
|
||||
- `backlog` (`limit`, по умолчанию 50) — бэклог по рангу: позиция, ключ, тема, статус, исполнитель, SP; в конце «ещё N»,
|
||||
если задач больше `limit`.
|
||||
Таблица `issues` SHALL получить колонку «SP». Описание `batch_create` SHALL перечислять `ensure_sprint_meta`,
|
||||
`ensure_sprint_state`, `ensure_rank` и `story_points` в `ensure_fields` с параметрами; хвостовой `refresh` и `board_id`
|
||||
(у `ensure_sprint`, команд спринта и `ensure_fields` с `story_points`) хаб дописывает сам (см. `commands`).
|
||||
|
||||
#### Scenario: Спринты проекта
|
||||
- **WHEN** сессия привязана к `AWPCA`, вызван `sprints`
|
||||
- **THEN** строки: активный `AWPCA_Sprint_3_Corrections`, будущие, затем закрытые; у каждой — задачи и SP «выполнено/всего»
|
||||
|
||||
#### Scenario: Бэклог с лимитом
|
||||
- **WHEN** `backlog {limit: 2}`, в бэклоге 188 задач
|
||||
- **THEN** две строки по рангу и «ещё 186»
|
||||
Loading…
x
Reference in New Issue
Block a user