Merge pull request 'Документация: хаб переименован в sdlc-hub (#47)' (#48) from feat/47-sdlc-docs into main
This commit is contained in:
commit
0cf4aa9535
@ -1,7 +1,7 @@
|
|||||||
# Архитектура
|
# Архитектура
|
||||||
|
|
||||||
Агент — один файл `src/agent.py` и запускатель `src/run.py` (Python 3.9, только стандартная библиотека). Тесты в `tests/` работают на фейках
|
Агент — один файл `src/agent.py` и запускатель `src/run.py` (Python 3.9, только стандартная библиотека). Тесты в `tests/` работают на фейках
|
||||||
Jira и хаба. Спека: `../jira-hub/openspec/changes/bridge-core/`, план агента: `docs/superpowers/plans/2026-10-11-bridge-core-agent.md` (план хаба: `../jira-hub/docs/superpowers/plans/2026-10-11-bridge-core-hub.md`).
|
Jira и хаба. Спека: `../sdlc-hub/openspec/changes/bridge-core/`, план агента: `docs/superpowers/plans/2026-10-11-bridge-core-agent.md` (план хаба: `../sdlc-hub/docs/superpowers/plans/2026-10-11-bridge-core-hub.md`).
|
||||||
|
|
||||||
## Разделы файла `src/agent.py`
|
## Разделы файла `src/agent.py`
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ Jira и хаба. Спека: `../jira-hub/openspec/changes/bridge-core/`, пл
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Настройки | `load_config` | читает `agent.json`, проверяет обязательные поля | — |
|
| Настройки | `load_config` | читает `agent.json`, проверяет обязательные поля | — |
|
||||||
| HTTP | `Http`, `HttpError`, `JiraClient`, `HubClient`, `multipart_file`, `wire_filename` | запросы; `Http.send` — запрос с готовым телом (JSON-вызов `call` идёт через него); `JiraClient` считает вызовы, повторяет 429/503 по `Retry-After` (до 5 запросов, не более 4 ожиданий), хранит время последнего вызова; `JiraClient.upload` — вложение `multipart/form-data` (таймаут не меньше 120 с); `JiraClient.download` (через `Http.fetch_bytes`) — содержимое вложения байтами, не больше предела (`TooBig`), перенаправление на другой адрес — `RedirectAway` без перехода (`_SameOriginRedirect`); `HubClient.file` — файл вложения у хаба (base64 в JSON), `HubClient.upload_file` — скачанный файл хабу (`POST /agent/files`) | `urllib` |
|
| HTTP | `Http`, `HttpError`, `JiraClient`, `HubClient`, `multipart_file`, `wire_filename` | запросы; `Http.send` — запрос с готовым телом (JSON-вызов `call` идёт через него); `JiraClient` считает вызовы, повторяет 429/503 по `Retry-After` (до 5 запросов, не более 4 ожиданий), хранит время последнего вызова; `JiraClient.upload` — вложение `multipart/form-data` (таймаут не меньше 120 с); `JiraClient.download` (через `Http.fetch_bytes`) — содержимое вложения байтами, не больше предела (`TooBig`), перенаправление на другой адрес — `RedirectAway` без перехода (`_SameOriginRedirect`); `HubClient.file` — файл вложения у хаба (base64 в JSON), `HubClient.upload_file` — скачанный файл хабу (`POST /agent/files`) | `urllib` |
|
||||||
| Папка | `FolderTransport` | транспорт `folder:` к хабу через общую папку: `req/<id>.json` → реле хаба → `resp/<id>.json`; ошибки как у `Http`; `HubClient` делегирует ему `call` (спека `jira-hub/openspec/changes/folder-transport/`) | `os`, `uuid` |
|
| Папка | `FolderTransport` | транспорт `folder:` к хабу через общую папку: `req/<id>.json` → реле хаба → `resp/<id>.json`; ошибки как у `Http`; `HubClient` делегирует ему `call` (спека `sdlc-hub/openspec/changes/folder-transport/`) | `os`, `uuid` |
|
||||||
| Журнал | `Journal`, `_parse_at` | дозапись `journal.jsonl`: `started` → `finished` → `acked`; восстановление; `prune` (из CLI — под блокировкой журнала) | файловая система |
|
| Журнал | `Journal`, `_parse_at` | дозапись `journal.jsonl`: `started` → `finished` → `acked`; восстановление; `prune` (из CLI — под блокировкой журнала) | файловая система |
|
||||||
| Исполнитель | `Executor` и `do_<тип>` | по одному методу на тип команды: читает Jira, пишет только разницу; `refresh` читает и отправляет состояние в хаб, затем (v13, параметр `history`) журнал изменений Jira — `refresh_history`: изменившиеся с `history.since` задачи этого прогона и стартовая выборка `history.jql`, `search` с `expand=changelog`, `POST /agent/history` пачками по 500; ответ не 2xx Jira или хаба — `history.error`/`backfill_error`, `refresh` остаётся `done`; `ensure_attachment` берёт файл вложения у хаба (`hub_file`: sha256 и размер, повреждение — `HubError` с повтором); `fetch_attachment` (v14) читает вложение в Jira, качает содержимое по адресу из `base_url` (предел `MAX_ATTACHMENT`, 10 МБ) и отдаёт хабу; в состоянии `refresh` у задачи — `attachments` (список без содержимого, `attachments_of`); доски — из параметров команд (`ensure_sprint.board_id`, `refresh.boards`, тип доски — `board_type`), `board_id` настроек — запасной | `JiraClient`, `HubClient` (`refresh` и файл в `ensure_attachment`), настройки хаба |
|
| Исполнитель | `Executor` и `do_<тип>` | по одному методу на тип команды: читает Jira, пишет только разницу; `refresh` читает и отправляет состояние в хаб, затем (v13, параметр `history`) журнал изменений Jira — `refresh_history`: изменившиеся с `history.since` задачи этого прогона и стартовая выборка `history.jql`, `search` с `expand=changelog`, `POST /agent/history` пачками по 500; ответ не 2xx Jira или хаба — `history.error`/`backfill_error`, `refresh` остаётся `done`; `ensure_attachment` берёт файл вложения у хаба (`hub_file`: sha256 и размер, повреждение — `HubError` с повтором); `fetch_attachment` (v14) читает вложение в Jira, качает содержимое по адресу из `base_url` (предел `MAX_ATTACHMENT`, 10 МБ) и отдаёт хабу; в состоянии `refresh` у задачи — `attachments` (список без содержимого, `attachments_of`); доски — из параметров команд (`ensure_sprint.board_id`, `refresh.boards`, тип доски — `board_type`), `board_id` настроек — запасной | `JiraClient`, `HubClient` (`refresh` и файл в `ensure_attachment`), настройки хаба |
|
||||||
| Самообновление | `read_update_state`, `write_update_state`, `Updater`, `launcher_version` | `update.json`; после `claim` без команды — проверка `agent_release`, скачивание, sha256, компиляция, `selftest`, `staged`; подтверждение `ok` новой версией; без запускателя — только подсказка в лог | `HubClient`, `subprocess` |
|
| Самообновление | `read_update_state`, `write_update_state`, `Updater`, `launcher_version` | `update.json`; после `claim` без команды — проверка `agent_release`, скачивание, sha256, компиляция, `selftest`, `staged`; подтверждение `ok` новой версией; без запускателя — только подсказка в лог | `HubClient`, `subprocess` |
|
||||||
|
|||||||
12
CLAUDE.md
12
CLAUDE.md
@ -1,11 +1,11 @@
|
|||||||
# jira-agent
|
# jira-agent
|
||||||
|
|
||||||
## Что это
|
## Что это
|
||||||
Клиент моста Jira для виртуалки с доступом к Jira банка. Опрашивает хаб `jira-hub` (Mac mini), выполняет команды
|
Клиент моста Jira для виртуалки с доступом к Jira банка. Опрашивает хаб `sdlc-hub` (Mac mini), выполняет команды
|
||||||
«желаемый результат» по правилу «проверь, потом сделай», ведёт журнал на диске и отдаёт хабу состояние задач.
|
«желаемый результат» по правилу «проверь, потом сделай», ведёт журнал на диске и отдаёт хабу состояние задач.
|
||||||
Главный сценарий: хаб ставит команду (например, создать задачу, перевести статус, перенести в спринт), агент
|
Главный сценарий: хаб ставит команду (например, создать задачу, перевести статус, перенести в спринт), агент
|
||||||
читает задачу в Jira, записывает только разницу и возвращает результат; хаб синхронизирует зеркало через `refresh`.
|
читает задачу в Jira, записывает только разницу и возвращает результат; хаб синхронизирует зеркало через `refresh`.
|
||||||
Спека: `../jira-hub/openspec/specs/` (`agent/spec.md`, `commands/spec.md`).
|
Спека: `../sdlc-hub/openspec/specs/` (`agent/spec.md`, `commands/spec.md`).
|
||||||
|
|
||||||
## Стек и ограничения
|
## Стек и ограничения
|
||||||
- Python 3.9.6 (как на виртуалке), только стандартная библиотека, без venv и зависимостей.
|
- Python 3.9.6 (как на виртуалке), только стандартная библиотека, без venv и зависимостей.
|
||||||
@ -15,7 +15,7 @@
|
|||||||
Шаблон без секретов — `src/agent.example.json`.
|
Шаблон без секретов — `src/agent.example.json`.
|
||||||
|
|
||||||
## Архитектура
|
## Архитектура
|
||||||
- `src/agent.py` — весь агент, один файл. Разделы в порядке файла: HTTP-клиенты (`Http`, `JiraClient`, `HubClient`; `FolderTransport` — транспорт `folder:` к хабу через общую папку, ошибки как у `Http`, спека `jira-hub/openspec/specs/agent/`),
|
- `src/agent.py` — весь агент, один файл. Разделы в порядке файла: HTTP-клиенты (`Http`, `JiraClient`, `HubClient`; `FolderTransport` — транспорт `folder:` к хабу через общую папку, ошибки как у `Http`, спека `sdlc-hub/openspec/specs/agent/`),
|
||||||
`Journal`, `Executor` (по методу `do_<тип>` на каждый тип команды), `Runner` (цикл claim → пауза → журнал →
|
`Journal`, `Executor` (по методу `do_<тип>` на каждый тип команды), `Runner` (цикл claim → пауза → журнал →
|
||||||
выполнение → отчёт), `Updater` (самообновление: `update.json`, скачивание, `selftest`, выход 75), CLI (`cmd_check`,
|
выполнение → отчёт), `Updater` (самообновление: `update.json`, скачивание, `selftest`, выход 75), CLI (`cmd_check`,
|
||||||
`cmd_selftest`, `cmd_run`, `cmd_prune`, `main`).
|
`cmd_selftest`, `cmd_run`, `cmd_prune`, `main`).
|
||||||
@ -48,12 +48,12 @@
|
|||||||
## Первая подсистема
|
## Первая подсистема
|
||||||
Исполнитель команд и цикл агента (спека `agent/spec.md`, `commands/spec.md`) — реализованы целиком: все типы команд,
|
Исполнитель команд и цикл агента (спека `agent/spec.md`, `commands/spec.md`) — реализованы целиком: все типы команд,
|
||||||
журнал, восстановление после перезапуска, CLI `run|check|selftest|prune`, самообновление через `run.py`.
|
журнал, восстановление после перезапуска, CLI `run|check|selftest|prune`, самообновление через `run.py`.
|
||||||
Последний change — `../jira-hub/openspec/changes/attachment-fetch/` (агент v14: список вложений в `refresh`, команда `fetch_attachment`; решения агента — `openspec/changes/agent-v14-attachment-fetch/design.md`), план — `docs/superpowers/plans/2026-10-22-attachment-fetch-agent.md`.
|
Последний change — `../sdlc-hub/openspec/changes/attachment-fetch/` (агент v14: список вложений в `refresh`, команда `fetch_attachment`; решения агента — `openspec/changes/agent-v14-attachment-fetch/design.md`), план — `docs/superpowers/plans/2026-10-22-attachment-fetch-agent.md`.
|
||||||
План и спека живут в `jira-hub`: `openspec/changes/bridge-core/` и `docs/superpowers/plans/2026-10-11-bridge-core-hub.md`; план агента лежит здесь: `docs/superpowers/plans/2026-10-11-bridge-core-agent.md`.
|
План и спека живут в `sdlc-hub`: `openspec/changes/bridge-core/` и `docs/superpowers/plans/2026-10-11-bridge-core-hub.md`; план агента лежит здесь: `docs/superpowers/plans/2026-10-11-bridge-core-agent.md`.
|
||||||
|
|
||||||
## Выкатка новой версии
|
## Выкатка новой версии
|
||||||
Самообновление (с v5): после merge PR агента в main — поднять `AGENT_VERSION` (если не поднят в PR) и опубликовать:
|
Самообновление (с v5): после merge PR агента в main — поднять `AGENT_VERSION` (если не поднят в PR) и опубликовать:
|
||||||
`uv run --project ../jira-hub jira-hub agent publish src/agent.py` (из основного checkout `jira-agent` на main).
|
`uv run --project ../sdlc-hub sdlc-hub agent publish src/agent.py` (из основного checkout `jira-agent` на main).
|
||||||
Через несколько минут MCP `agent_status` должен показать «обновление: ok v<старая> → v<новая>»; откат — «откат с v<N>…»
|
Через несколько минут MCP `agent_status` должен показать «обновление: ok v<старая> → v<новая>»; откат — «откат с v<N>…»
|
||||||
(причина — в логе агента на виртуалке). Это пункт чеклиста «закрывай» для PR агента. `run.py` публикацией не
|
(причина — в логе агента на виртуалке). Это пункт чеклиста «закрывай» для PR агента. `run.py` публикацией не
|
||||||
обновляется — только вручную через общую папку.
|
обновляется — только вручную через общую папку.
|
||||||
|
|||||||
10
README.md
10
README.md
@ -1,12 +1,12 @@
|
|||||||
# jira-agent
|
# jira-agent
|
||||||
|
|
||||||
Клиент моста Jira для виртуалки с доступом к Jira банка. Агент опрашивает хаб (`jira-hub` на Mac mini),
|
Клиент моста Jira для виртуалки с доступом к Jira банка. Агент опрашивает хаб (`sdlc-hub` на Mac mini),
|
||||||
выполняет команды «желаемый результат» в Jira по правилу «проверь, потом сделай», ведёт журнал на диске
|
выполняет команды «желаемый результат» в Jira по правилу «проверь, потом сделай», ведёт журнал на диске
|
||||||
и возвращает хабу состояние задач. Один файл `src/agent.py` и запускатель `src/run.py`, только стандартная
|
и возвращает хабу состояние задач. Один файл `src/agent.py` и запускатель `src/run.py`, только стандартная
|
||||||
библиотека, Python 3.9.
|
библиотека, Python 3.9.
|
||||||
|
|
||||||
Спека: `../jira-hub/openspec/specs/agent/spec.md` (вместе с `commands/` и `hub-api/`).
|
Спека: `../sdlc-hub/openspec/specs/agent/spec.md` (вместе с `commands/` и `hub-api/`).
|
||||||
Хаб, очередь команд и зеркало задач живут в репозитории `jira-hub`; агент с ним общается только по HTTP.
|
Хаб, очередь команд и зеркало задач живут в репозитории `sdlc-hub`; агент с ним общается только по HTTP.
|
||||||
|
|
||||||
## Доставка на виртуалку
|
## Доставка на виртуалку
|
||||||
|
|
||||||
@ -14,7 +14,7 @@
|
|||||||
виртуалке, например `~/jira-agent/`. Запускать из этого каталога, не из общей папки.
|
виртуалке, например `~/jira-agent/`. Запускать из этого каталога, не из общей папки.
|
||||||
2. Переименовать `agent.example.json` в `agent.json` и заполнить:
|
2. Переименовать `agent.example.json` в `agent.json` и заполнить:
|
||||||
- `hub_url` — `http://<адрес Mac mini>:8790`, или, если сеть до Mac mini закрыта VPN (Континент), `folder:/Volumes/My Shared Files/RSHB/jira-bridge` — обмен через общую папку UTM (на хабе должна быть задана настройка `relay_dir`, см. README хаба);
|
- `hub_url` — `http://<адрес Mac mini>:8790`, или, если сеть до Mac mini закрыта VPN (Континент), `folder:/Volumes/My Shared Files/RSHB/jira-bridge` — обмен через общую папку UTM (на хабе должна быть задана настройка `relay_dir`, см. README хаба);
|
||||||
- `hub_token` — агентский токен из `jira-hub tokens` на Mac mini;
|
- `hub_token` — агентский токен из `sdlc-hub tokens` на Mac mini;
|
||||||
- `jira.base_url` — адрес Jira банка;
|
- `jira.base_url` — адрес Jira банка;
|
||||||
- `jira.auth` — `{"type": "basic", "user": ..., "password": ...}` или `{"type": "bearer", "token": ...}`;
|
- `jira.auth` — `{"type": "basic", "user": ..., "password": ...}` или `{"type": "bearer", "token": ...}`;
|
||||||
- `verify_ssl`, `ca_bundle` — при корпоративном сертификате (см. ограничение 2 ниже);
|
- `verify_ssl`, `ca_bundle` — при корпоративном сертификате (см. ограничение 2 ниже);
|
||||||
@ -88,7 +88,7 @@ nohup python3 -u run.py > agent.log 2>&1 &
|
|||||||
|
|
||||||
## Самообновление
|
## Самообновление
|
||||||
|
|
||||||
С версии 5 агент обновляется сам. После `jira-hub agent publish` на Mac mini хаб сообщает новую версию в ответе на
|
С версии 5 агент обновляется сам. После `sdlc-hub agent publish` на Mac mini хаб сообщает новую версию в ответе на
|
||||||
`claim`. Агент в паузе между командами (очередь пуста, отчёты подтверждены) скачивает файл по `GET /agent/release`,
|
`claim`. Агент в паузе между командами (очередь пуста, отчёты подтверждены) скачивает файл по `GET /agent/release`,
|
||||||
сверяет sha256, компилирует, проверяет `AGENT_VERSION`, кладёт рядом `agent.py.new`, запускает его `selftest` и выходит
|
сверяет sha256, компилирует, проверяет `AGENT_VERSION`, кладёт рядом `agent.py.new`, запускает его `selftest` и выходит
|
||||||
с кодом 75. `run.py` копирует текущий `agent.py` в `agent.py.prev`, ставит новый и запускает его в пробном режиме:
|
с кодом 75. `run.py` копирует текущий `agent.py` в `agent.py.prev`, ставит новый и запускает его в пробном режиме:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"hub_url": "http://192.168.0.106:8790",
|
"hub_url": "http://192.168.0.106:8790",
|
||||||
"hub_token": "агентский токен из `jira-hub tokens`",
|
"hub_token": "агентский токен из `sdlc-hub tokens`",
|
||||||
"jira": {
|
"jira": {
|
||||||
"base_url": "https://sdlc.go.rshbank.ru/jira",
|
"base_url": "https://sdlc.go.rshbank.ru/jira",
|
||||||
"auth": {"type": "basic", "user": "логин", "password": "пароль", "token": ""}
|
"auth": {"type": "basic", "user": "логин", "password": "пароль", "token": ""}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user