145 lines
16 KiB
Markdown
145 lines
16 KiB
Markdown
## MODIFIED Requirements
|
||
|
||
### Requirement: Инструменты
|
||
| Инструмент | Параметры | Результат |
|
||
|---|---|---|
|
||
| `projects` | — | таблица: метка, название, доска, тип доски («неизвестен», пока агент не определил), число своих задач; в привязанной сессии текущий проект отмечен |
|
||
| `project_create` | `label`, `name`, `board_id` (необязательно) | `POST /projects` с автором `claude`: проект, id пакета обновления и фрагмент `.mcp.json` для репозитория проекта (см. ниже); 409/422 — текст ошибки |
|
||
| `issues` | фильтры как у `GET /issues` (кроме `project` — его задаёт привязка), `limit` (по умолчанию 50) | таблица: ключ, тема (до 80 символов), статус, срок, исполнитель, спринт, статус по факту |
|
||
| `issue` | `key` | поля, связи (обе стороны, с типом и направлением), заметки, последние команды, комментарии: «комментарии (N):» и 5 последних (номер «#<comment_id>», автор, время, текст до 300 символов с «…»), «ещё M», если их больше 5; без комментариев — «комментариев нет»; у комментария со ссылками на вложения — строка «файлы: #<id> <имя>, …»; затем вложения (см. «Вложения в MCP») |
|
||
| `comment` | `key`, `comment_id` (номер из ответа `issue`, «#» в начале допускается) | один комментарий целиком по `GET /issues/{key}`: строка «<key> #<id> <автор>, создан <created>» (и «, изменён <updated>», если `updated` есть и отличается от `created`), под ней полный текст с переносами строк; нет такого номера — «у <key> нет комментария #<id>»; есть ссылки на вложения — после текста строка «вложения:» и по строке на каждое: «#<id> <имя> (<размер>)» |
|
||
| `attachment` | `key`, `attachment` (номер вложения «#<id>» или «<id>», иначе — точное имя файла), `wait_seconds` (по умолчанию 120, не больше 600) | скачивает вложение и отдаёт путь к локальной копии (см. «Вложения в MCP») |
|
||
| `notes_set` | `key`, подмножество полей заметок | обновлённые заметки |
|
||
| `batch_create` | `title`, `commands` (список объектов по контракту `commands`; у `ensure_attachment` вместо `file` можно `path`) | `id`, `estimate_seconds`, число команд; 422 — текст ошибки валидации |
|
||
| `batch_status` | `id` | статусы команд, ошибки, оценка остатка |
|
||
| `batch_wait` | `id`, `timeout_minutes` (≤ 60) | как `batch_status`, возвращается по завершении или по таймауту |
|
||
| `batches` | `limit` | последние пакеты со статусом |
|
||
| `command_retry` | `id` | новый пакет |
|
||
| `batch_cancel` | `id` | вид пакета; для команд пакета, уже взятых агентом, — строка «команда #N уже у агента и будет выполнена; остановить — `POST /commands/N/cancel` с `force: true`» |
|
||
| `refresh` | `keys` или `full`, `wait` (bool) | без `wait` — строка с id поставленного пакета; с `wait` — итог пакета, как у `batch_wait` |
|
||
| `agent_status` | — | онлайн/офлайн, версия, текущая команда, довыданные команды (id, тип, число выдач), 429 за сутки, версия настроек; публикация агента («публикация: v<N> от <дата>» или «публикации нет»), состояние обновления («обновление: <state> v<from> → v<to>»), запускатель («запускатель: v<N>», «без запускателя» или, пока `agent_reported = false`, «запускатель: неизвестно (агент ещё не выходил на связь после перезапуска хаба)»), `update_hint`, если он есть |
|
||
| `sync_log` | `limit` | последние `sync_run` |
|
||
| `settings_get`, `settings_set` | ключ, значение | текущее значение / новая `settings_version` |
|
||
|
||
Разрез по проекту и поведение без привязки — требование «Привязка сессии к проекту».
|
||
|
||
Описание инструмента `batch_create` SHALL перечислять параметры каждого типа команды (обязательные, необязательные в
|
||
`[ ]`, формат значения) и собираться из описания параметров в коде хаба (см. `commands`), а не вручную.
|
||
|
||
`ensure_attachment` в `batch_create` SHALL принимать вместо `file` параметр `path` — абсолютный путь к локальному файлу на
|
||
машине MCP-сервера. До постановки пакета MCP SHALL прочитать файл, загрузить его `POST /files` и заменить `path` на
|
||
`file`; `filename` по умолчанию — имя файла из `path`. Нет файла, нет прав, не файл, больше 10 МБ — ответ инструмента
|
||
с причиной и путём, пакет не ставится. Передан и `path`, и `file` — ответ «у ensure_attachment либо path, либо file».
|
||
|
||
Описание инструмента `batch_create` SHALL сообщать, что метку проекта сессии хаб дописывает в `ensure_issue` сам, метки
|
||
других проектов запрещены, а команды над задачами вне проекта отклоняются; `board_id` для `ensure_sprint` выставляет хаб.
|
||
|
||
Ответ `project_create` SHALL содержать фрагмент `.mcp.json`
|
||
`{"mcpServers": {"jira-hub": {"command": "uv", "args": ["run", "--project", "<корень хаба>", "jira-hub", "mcp",
|
||
"--project", "<метка>"]}}}`, где корень хаба — корень репозитория, из которого загружен пакет текущего процесса MCP
|
||
(вычисляется от расположения пакета, без зашитого пути), и указание: положить файл в корень репозитория проекта (слить
|
||
с имеющимся `.mcp.json`) и переподключить MCP (`/mcp` → reconnect, одобрить сервер проекта).
|
||
|
||
Автор команд из MCP SHALL быть `claude`; из API без автора — `api`.
|
||
|
||
#### Scenario: Пакет из чата
|
||
- **WHEN** `batch_create {title: "1538 в спринт 2", commands: [ensure_fields{…}, ensure_link{…}, ensure_sprint{…}]}`
|
||
- **THEN** пакет создан с четырьмя командами (три + `refresh`), ответ содержит оценку в минутах
|
||
|
||
#### Scenario: Проект из чата
|
||
- **WHEN** сессия без привязки, `project_create {label: "STOCKS_DRRK", name: "Запасы ДРРК", board_id: 5120}`
|
||
- **THEN** проект создан, ответ содержит id пакета обновления и фрагмент `.mcp.json` с `"--project", "STOCKS_DRRK"`
|
||
|
||
#### Scenario: Ошибка с файлом из чата
|
||
- **WHEN** `batch_create {title: "Ошибка ОСВ 60", commands: [ensure_issue{temp_key: new:1, issue_type: bug, …},
|
||
ensure_attachment{key: new:1, path: "/Users/…/ОСВ сч. 60 за 2 кв. 2026.xlsx"}]}`
|
||
- **THEN** файл загружен в хаб; пакет создан с `ensure_attachment {key: new:1, file: <sha>, filename: "ОСВ сч. 60 за 2 кв.
|
||
2026.xlsx"}` и хвостовым `refresh`
|
||
|
||
#### Scenario: Файла нет
|
||
- **WHEN** тот же вызов, файла по `path` нет
|
||
- **THEN** ответ «файл не найден: <path>», пакет не создан, в хаб ничего не загружено
|
||
|
||
#### Scenario: Ожидание результата
|
||
- **WHEN** `batch_wait {id, timeout_minutes: 10}` и пакет завершился через 6 минут
|
||
- **THEN** ответ через 6 минут со статусами всех команд
|
||
|
||
#### Scenario: Статус агента с довыдачей
|
||
- **WHEN** агент на связи, команда 40 выдана дважды и ещё без отчёта
|
||
- **THEN** ответ `agent_status` содержит «агент онлайн» и строку о команде 40 с числом выдач 2
|
||
|
||
#### Scenario: Отмена пакета с командой у агента
|
||
- **WHEN** `batch_cancel {id: 9}`, команда 30 пакета в `claimed`
|
||
- **THEN** ответ содержит вид пакета и строку «команда #30 уже у агента и будет выполнена; остановить — …»
|
||
|
||
#### Scenario: Статус агента после отката
|
||
- **WHEN** опубликована v7, агент v6 под запускателем v1 прислал `update_state = rolled_back` для v7
|
||
- **THEN** ответ `agent_status` содержит «публикация: v7 от …», «обновление: rolled_back v6 → v7», «запускатель: v1» и
|
||
«откат с v7 на v6: …»
|
||
|
||
#### Scenario: Статус агента сразу после перезапуска хаба
|
||
- **WHEN** хаб перезапущен, агент ещё не прислал `claim`
|
||
- **THEN** ответ `agent_status` содержит «запускатель: неизвестно (агент ещё не выходил на связь после перезапуска
|
||
хаба)» и не содержит «без запускателя» и «агент запущен без run.py»
|
||
|
||
#### Scenario: Задача с семью комментариями
|
||
- **WHEN** `issue {key: "AURORA-9001"}`, у задачи 7 комментариев, у самого нового текст 500 символов
|
||
- **THEN** ответ содержит «комментарии (7):», 5 последних комментариев с номерами «#<comment_id>» (самый новый — первым, обрезан до 300 символов с «…») и «ещё 2»
|
||
|
||
#### Scenario: Комментарий целиком
|
||
- **WHEN** у задачи `AURORA-9001` комментарий `#101` длиной 800 символов с переносами строк, вызван `comment {key: "AURORA-9001", comment_id: "101"}`
|
||
- **THEN** ответ — «AURORA-9001 #101 <автор>, создан <created>» и полный текст комментария без обрезки, переносы строк сохранены
|
||
|
||
#### Scenario: Нет такого комментария
|
||
- **WHEN** `comment {key: "AURORA-9001", comment_id: "999"}`, у задачи нет комментария 999
|
||
- **THEN** ответ «у AURORA-9001 нет комментария #999»
|
||
|
||
## ADDED Requirements
|
||
|
||
### Requirement: Вложения в MCP
|
||
`issue` SHALL после комментариев выводить «вложения (N):» и по строке на каждое вложение (новые сверху): «#<id> <имя>
|
||
(<размер>) — <автор>, <created>», дальше через запятую: «в описании», если на вложение ссылается описание, «в #<comment_id>»
|
||
для каждого ссылающегося комментария, «скачано», если `state = ready`, «больше 10 МБ — только в Jira» для таких файлов;
|
||
без вложений — «вложений нет». Размер — в байтах, КБ или МБ с одним знаком после запятой («512 Б», «234,4 КБ», «2,3 МБ»);
|
||
неизвестный — «размер неизвестен».
|
||
|
||
`attachment` SHALL:
|
||
1. найти вложение по `GET /issues/{key}`: по номеру, иначе по точному имени (несколько с одним именем — самое новое, в
|
||
ответ строка «у <key> N вложений «<имя>», взято самое новое #<id>»); не найдено — «у <key> нет вложения «<значение>»;
|
||
список — issue <key>», в хаб больше не ходить;
|
||
2. `POST /attachments/{id}/fetch` с автором `claude`; 413 — «файл больше 10 МБ (<размер>) — скачайте в Jira:
|
||
задача <key>, вложение «<имя>»»; 409 и прочие ошибки хаба — их текст;
|
||
3. пока `state = fetching` — опрашивать `GET /attachments/{id}` раз в 2 с, не дольше `wait_seconds`; не дождался —
|
||
«скачивание ещё идёт (команда #<command_id>, агент <онлайн/офлайн>); вызовите attachment ещё раз — вторая команда не
|
||
поставится»; `failed` — «не удалось скачать: <error>»;
|
||
4. при `ready` — `GET /attachments/{id}/content` и записать файл в `<каталог данных хаба>/downloads/<id>/<имя>`, где имя —
|
||
`filename` с заменой `/`, `\`, `:` и управляющих символов на `_` (пустое — `attachment-<id>`); каталог с правами
|
||
`0700`; запись через временный файл и переименование; если там уже лежит файл того же размера — не перезаписывать;
|
||
5. ответить «<абсолютный путь>» отдельной строкой и под ним «<имя> (<размер>), <mime_type>, задача <key>».
|
||
|
||
#### Scenario: Скриншот из комментария
|
||
- **WHEN** `comment {key: "AURORA-1650", comment_id: "101"}` показал «вложения: #31337 скрин 1.png (234,4 КБ)»; вызван
|
||
`attachment {key: "AURORA-1650", attachment: "#31337"}`, агент онлайн, файла у хаба нет
|
||
- **THEN** поставлена `fetch_attachment`; через несколько секунд ответ — путь
|
||
`…/jira-hub/downloads/31337/скрин 1.png` и строка «скрин 1.png (234,4 КБ), image/png, задача AURORA-1650»; файл по пути
|
||
читается
|
||
|
||
#### Scenario: Повторный вызов
|
||
- **WHEN** тот же вызов второй раз, файл у хаба (`ready`) и в `downloads/31337/`
|
||
- **THEN** ответ сразу, команд в очереди не прибавилось
|
||
|
||
#### Scenario: Агент не успел
|
||
- **WHEN** `attachment {…, wait_seconds: 30}`, агент занят долгим `refresh`
|
||
- **THEN** через 30 с ответ «скачивание ещё идёт (команда #N, агент онлайн); вызовите attachment ещё раз — вторая
|
||
команда не поставится»
|
||
|
||
#### Scenario: По имени
|
||
- **WHEN** `attachment {key: "AURORA-1650", attachment: "ОСВ 60.xlsx"}`, вложение с таким именем одно
|
||
- **THEN** скачивается оно; путь оканчивается на `/ОСВ 60.xlsx`
|
||
|
||
#### Scenario: Вложения в карточке
|
||
- **WHEN** `issue {key: "AURORA-1650"}`, у задачи вложения #31337 «скрин 1.png» (на него ссылается комментарий 101,
|
||
скачано) и #31338 «запись.mp4» на 25 МБ
|
||
- **THEN** в ответе «вложения (2):», строка #31338 с «больше 10 МБ — только в Jira», строка #31337 с «в #101, скачано»; у
|
||
комментария 101 строка «файлы: #31337 скрин 1.png»
|