2026-10-15 12:18:35 +04:00

12 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Маршруты агента

Хаб SHALL предоставлять агенту следующие маршруты (все под агентским токеном):

  • POST /agent/claim {agent_version, settings_version, last_jira_call_at, update_state, launcher_version} — долгий запрос до 30 с; ответ {command: {id, type, params, pause_seconds}, settings_version, agent_release} или {command: null, settings_version, agent_release}, где agent_release — {version, sha256} опубликованной версии агента или null; обновляет agent_status (last_jira_call_at = null не затирает прежнее значение). update_state (объект или null, error хранится до 500 символов) и launcher_version (целое или null) необязательны; хаб SHALL хранить последние значения в памяти процесса, значения неверного типа игнорировать, не отвергая claim. Если есть команда в claimed, claim SHALL выдать её снова (повторная выдача, см. commands), а не следующую из очереди.
  • GET /agent/settings — настройки для агента (без токенов).
  • GET /agent/commands/{id} — команда по id (для восстановления из журнала), включая pause_seconds.
  • POST /agent/commands/{id}/result {status, result, error, jira_calls, rate_limited} — идемпотентно: повторный отчёт по команде в терминальном статусе отвечает 200 без изменений, кроме позднего отчёта done с result.key по ensure_issue в cancelled или failed без результата (результат записывается, статус не меняется, заметка new:N переносится на ключ). Отчёт по команде в queued SHALL отвергаться 409 not_claimed. error хаб SHALL обрезать до 1500 символов.
  • POST /agent/state {command_id, issues: [...], links: [...], neighbor_keys: [...], page, last_page} — загрузка состояния пачками; neighbor_keys — ключи вне базовой JQL, дочитанные по связям; хаб обновляет зеркало и sync_run. Каждая пачка применяется независимо; page и last_page необязательны и хабом не используются. Поле задачи comments необязательно; если оно есть, хаб SHALL до записи проверить его форму: список объектов, id — непустая строка, body — строка, author, created, updated — строка или null; нарушение — 422 bad_state с ключом задачи и именем поля, пачка не применяется.
  • GET /agent/known-keys — ключи зеркала (для определения соседей).
  • GET /agent/release — опубликованная версия агента {version, sha256, content} (content — текст agent.py); нет публикации или файл не сходится с манифестом по sha256 — 404 no_release.

Scenario: Выдача с подстановкой ключа

  • WHEN следующая команда ссылается на new:60, а ensure_issue для new:60 завершилась с AURORA-1590
  • THEN claim отдаёт команду с AURORA-1590 в параметрах

Scenario: Повторный отчёт

  • WHEN агент дважды прислал result для команды 15
  • THEN второй ответ 200, статус и результат не изменились

Scenario: Отчёт по невыданной команде

  • WHEN POST /agent/commands/16/result с status = done, команда 16 в queued
  • THEN 409 not_claimed, команда осталась queued

Scenario: Длинная ошибка

  • WHEN агент прислал failed с error длиной 5000 символов
  • THEN в command.error первые 1500 символов

Scenario: Поздний отчёт после предела выдач

  • WHEN ensure_issue {temp_key: new:8, …} переведена хабом в failed «агент не отчитался после 3 выдач», затем агент прислал done с result.key = AURORA-1630
  • THEN команда failed, в result — AURORA-1630; заметка new:8 перенесена на AURORA-1630

Scenario: Публикация в ответе claim

  • WHEN опубликована v6, агент v5 отправил claim, команд нет
  • THEN ответ {command: null, settings_version, agent_release: {version: 6, sha256: …}}

Scenario: Состояние обновления от агента

  • WHEN агент прислал в claim update_state = {state: rolled_back, from_version: 6, to_version: 7, error: "код 1 через 3 с"} и launcher_version = 1
  • THEN GET /agent отдаёт это update_state, launcher_version = 1 и update_hint «откат с v7 на v6: код 1 через 3 с»

Scenario: Скачивание версии

  • WHEN агентским токеном GET /agent/release, опубликована v6
  • THEN 200 {version: 6, sha256, content}, sha256 от content в UTF-8 равен sha256; клиентским токеном — 401; без публикации — 404 no_release

Scenario: Неверный комментарий в пачке

  • WHEN POST /agent/state с задачами X и Y, у Y комментарий {id: "7", body: 42}
  • THEN 422 bad_state с ключом Y и полем body; ни X, ни Y в зеркале не изменились

Requirement: Маршруты интерфейсов

Хаб SHALL предоставлять интерфейсам (MCP, позже просмотрщик) следующие маршруты под клиентским токеном:

  • GET /issues с фильтрами sprint, assignee, work_kind, fact_status, status, label, epic, neighbor, q (подстрока темы), limit/offset — строки зеркала (все поля issue) с fact_status и work_kind из заметок; сокращение до карточки — дело интерфейса.
  • GET /issues/{key} — задача целиком: поля, epic_summary (тема эпика из зеркала или null), связи в обе стороны (links_out: [{target_key, link_type, summary, status}], links_in: [{source_key, link_type, summary, status}], где summary и status — связанной задачи из зеркала или null, если её там нет), заметки, последние 10 команд по ней, comments: [{comment_id, author, created, updated, body}] — все комментарии, новые сверху (по created, затем comment_id, по убыванию).
  • PUT /issues/{key}/note — заметки (частичное обновление, updated_by из тела).
  • POST /batches {title, author, commands: [...]} → {id, estimate_seconds}; 422 при неизвестном типе, неверных параметрах (в том числе неверного типа значения), временном ключе без ensure_issue, двух и более ensure_issue с одинаковой summary (сравнение после обрезки пробелов по краям; в ответе перечислены повторяющиеся темы).
  • GET /batches?limit=, GET /batches/{id} (с командами), POST /batches/{id}/cancel — отменяет queued команды пакета; ответ — вид пакета с полем still_claimed: список {id, type} команд пакета в claimed (они будут выполнены агентом; остановить — отмена команды с force).
  • POST /commands/{id}/retry — новая команда с теми же параметрами в новом пакете «Повтор команды N».
  • POST /commands/{id}/cancel — только для queued; для claimed — 409, если не передан force: true.
  • POST /refresh {keys | jql | full: true} → пакет из одного refresh.
  • GET /agent, GET /sync-runs?limit=, GET /settings, PUT /settings (частично; поднимает settings_version; ответ — все настройки после записи, как у GET /settings, включая settings_version).

Scenario: Фильтр по спринту

  • WHEN GET /issues?sprint=Спринт 2
  • THEN только задачи с таким sprint, отсортированы по сроку, затем по ключу

Scenario: Отмена взятой команды

  • WHEN POST /commands/15/cancel без force, команда claimed
  • THEN 409 с claimed_at; с force: true — cancelled, следующий отчёт агента по ней принимается, статус не меняется

Scenario: Поздний отчёт по отменённому созданию

  • WHEN ensure_issue {temp_key: new:7, …} отменена с force: true, затем агент прислал done с result.key = AURORA-1620
  • THEN команда cancelled, в result — AURORA-1620; заметка new:7 перенесена на AURORA-1620

Scenario: Дубль темы в пакете

  • WHEN POST /batches с двумя ensure_issue, у обеих summary = "Шахматка: комментарии"
  • THEN 422 с темой «Шахматка: комментарии», пакет не создан

Scenario: Тема не строка

  • WHEN POST /batches с ensure_issue {temp_key: new:1, summary: 42, …}
  • THEN 422 с указанием параметра summary, пакет не создан

Scenario: Отмена пакета с командой у агента

  • WHEN в пакете 9 команда 30 claimed, команды 31 и 32 queued; POST /batches/9/cancel
  • THEN 31 и 32 cancelled; в ответе still_claimed = [{id: 30, type: …}]; 30 остаётся claimed

Scenario: Ответ на запись настроек

  • WHEN PUT /settings {relay_dir: "/Volumes/externalSSD/utm/rshb/jira-bridge"}
  • THEN 200; ответ содержит relay_dir с записанным значением, новую settings_version и остальные настройки; токенов в ответе нет

Scenario: Карточка с комментариями и связями

  • WHEN у AURORA-9001 два комментария (14.10 и 15.10), исходящая связь на AURORA-9002 («API свода», «Новая») и на AURORA-1, которой нет в зеркале; эпик AURORA-9100 «Тестовый эпик»
  • THEN GET /issues/AURORA-9001 отдаёт comments с комментарием от 15.10 первым, у связи на AURORA-9002 — summary = "API свода", status = "Новая", у связи на AURORA-1 — summary = null, status = null; epic_summary = "Тестовый эпик"