Andrey Epifancev 94a7b20b27 docs(openspec): архив bridge-core, спеки ядра моста в openspec/specs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:48:52 +04:00

68 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# agent Specification
## Purpose
TBD - created by archiving change bridge-core. Update Purpose after archive.
## Requirements
### Requirement: Состав и настройки агента
Агент SHALL состоять из одного файла `agent.py` (Python ≥ 3.9, только стандартная библиотека) и файла `agent.json`:
`hub_url`, `hub_token`, `jira.base_url`, `jira.auth` (`basic` с `user`/`password` или `bearer` с `token`), `verify_ssl`,
`ca_bundle`, `timeout`, `poll_seconds`. Всё остальное (id полей, типы, карта переходов, типы связей, доска, темп) агент
SHALL получать от хаба при старте и при изменении `settings_version`. Учётные данные Jira MUST NOT отправляться в хаб
и MUST NOT попадать в журнал и логи.
#### Scenario: Проверка без записи
- **WHEN** `python3 agent.py check`
- **THEN** агент печатает доступность хаба (версия настроек) и Jira (`GET /myself`), в Jira ничего не пишет
### Requirement: Цикл выполнения
Агент SHALL работать одним процессом: `claim` к хабу (долгий запрос) → при получении команды: досыпать до
`pause_seconds` от последнего вызова Jira → запись «started» в журнал → выполнение по контракту `commands` → запись
«finished» с результатом → отчёт хабу, повторяемый до подтверждения. Одна команда в полёте. При изменении
`settings_version` в ответе `claim` агент SHALL перечитать настройки до выполнения команды.
#### Scenario: Остановка между командами
- **WHEN** получен Ctrl-C во время выполнения команды
- **THEN** текущая команда доделывается и отчёт отправляется, затем процесс завершается
### Requirement: Журнал на диске и восстановление
Агент SHALL вести `journal.jsonl` (только дозапись) рядом с собой: строки `started {command_id, at}`, `finished {command_id,
status, result, error, jira_calls, rate_limited}`, `acked {command_id}`. При старте агент SHALL: отправить хабу все
`finished` без `acked`; для `started` без `finished` — выполнить команду заново по правилу «проверь, потом сделай»
(запросив её параметры у хаба по id). Команда `python3 agent.py prune` SHALL удалять из журнала записи с `acked` старше
30 дней.
#### Scenario: Падение после ответа Jira
- **WHEN** агент упал между `POST /issue` и записью `finished`, затем перезапущен
- **THEN** агент находит в журнале `started` без `finished`, запрашивает команду у хаба, находит созданную задачу поиском
дубля и отчитывается `done` с её ключом; второй задачи нет
### Requirement: Ограничение темпа и 429
Агент SHALL помнить время последнего вызова Jira (любого) и не начинать команду раньше `pause_seconds` после него.
На HTTP 429 и 503 агент SHALL ждать `Retry-After` (иначе 60 с × номер попытки) и повторять тот же запрос до 5 раз,
считая попытки в `rate_limited`; после 5 неудач — `failed`. Пауза между записями внутри одной команды — по зазору типа команды.
#### Scenario: 429 с Retry-After
- **WHEN** Jira ответила 429 с `Retry-After: 90`
- **THEN** агент ждёт 90 с, повторяет тот же запрос; в отчёте `rate_limited = 1`
### Requirement: Чтение состояния
`refresh` SHALL выполняться запросом `search` (`jql`, `fields` = поля зеркала включая `issuelinks` и спринт,
`maxResults = 100`, постранично) и отправляться хабу пачками по 100 задач со связями; ключи из `issuelinks`, которых нет
в выборке и в зеркале хаба (хаб сообщает список известных), агент SHALL дочитать одним `search` по `key in (...)`
и отправить с признаком `neighbor`.
#### Scenario: Полная синхронизация
- **WHEN** `refresh {jql: "project = AURORA AND labels = AWPCA"}` при 180 задачах
- **THEN** 2 вызова `search` + 1 на соседей; `sync_run.issues_count = 180 + соседи`
### Requirement: Доставка и запуск
README агента SHALL описывать: копирование `agent.py` и `agent.example.json` через общую папку, заполнение `agent.json`,
`check`, запуск в терминале и через `nohup` с логом, опциональный launchd-plist, `prune`. Версия агента SHALL быть в
константе файла и в каждом отчёте; хаб предупреждает в `agent_status`, если версия ниже минимальной из настроек.
#### Scenario: Устаревший агент
- **WHEN** агент версии 1 выходит на связь, а в настройках `min_agent_version = 2`
- **THEN** `agent_status.warning` = «обновите агента», команды выдаются по-прежнему