docs(agent): fix round 1 — OpenSpec-раздел в CLAUDE.md, README (префикс лога, timeout/poll, 429), оговорка проверки 3.9
- CLAUDE.md: восстановлен раздел «OpenSpec и superpowers» из шаблона; убрана фраза про задачу 7; тесты описаны по областям; оговорка про проверку 3.9 (ast не ловит API, только прогон на 3.9.6). - README: пример вывода check с префиксом времени; timeout и poll_seconds в доставке; 429/503 — не более 4 ожиданий, Retry-After в HTTP-date не разбирается. - ARCHITECTURE.md: формулировка повторов 429/503. - tests/test_py39.py: комментарий с ограничением проверки. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Typ5sXWNMFirr2va2uL8o
This commit is contained in:
parent
54f65d0333
commit
4eaad42d15
@ -8,7 +8,7 @@ Jira и хаба. Спека: `../jira-hub/openspec/changes/bridge-core/`, пл
|
||||
| Раздел | Классы и функции | Ответственность | Что использует |
|
||||
|---|---|---|---|
|
||||
| Настройки | `load_config` | читает `agent.json`, проверяет обязательные поля | — |
|
||||
| HTTP | `Http`, `HttpError`, `JiraClient`, `HubClient` | запросы; `JiraClient` считает вызовы, повторяет 429/503 по `Retry-After` (до 5 попыток), хранит время последнего вызова | `urllib` |
|
||||
| HTTP | `Http`, `HttpError`, `JiraClient`, `HubClient` | запросы; `JiraClient` считает вызовы, повторяет 429/503 по `Retry-After` (до 5 запросов, не более 4 ожиданий), хранит время последнего вызова | `urllib` |
|
||||
| Журнал | `Journal`, `_parse_at` | дозапись `journal.jsonl`: `started` → `finished` → `acked`; восстановление; `prune` | файловая система |
|
||||
| Исполнитель | `Executor` и `do_<тип>` | по одному методу на тип команды: читает Jira, пишет только разницу; `refresh` читает и отправляет состояние в хаб | `JiraClient`, `HubClient` (только `refresh`), настройки хаба |
|
||||
| Цикл | `Runner` | claim, пауза до команды, журнал, выполнение, отчёт до подтверждения, восстановление при старте | `HubClient`, `JiraClient`, `Journal`, `Executor` |
|
||||
|
||||
18
CLAUDE.md
18
CLAUDE.md
@ -9,8 +9,8 @@
|
||||
|
||||
## Стек и ограничения
|
||||
- Python 3.9.6 (как на виртуалке), только стандартная библиотека, без venv и зависимостей.
|
||||
- Запрещено: синтаксис 3.10+ (`match`, `X | Y` в аннотациях, `dict | dict`), сторонние импорты.
|
||||
Проверяет `tests/test_py39.py` (разбор с `feature_version=(3, 9)` и разрешённый список импортов).
|
||||
- Запрещено: синтаксис 3.10+ и сторонние импорты.
|
||||
`tests/test_py39.py` ловит синтаксис 3.10+ (match и т. п.) и сторонние импорты; `X | Y` в аннотациях и API новее 3.9 подтверждает только прогон на /usr/bin/python3 3.9.6.
|
||||
- `agent.json` содержит учётные данные Jira — не коммитить, не отправлять в хаб, не выносить с виртуалки.
|
||||
Шаблон без секретов — `src/agent.example.json`.
|
||||
|
||||
@ -34,11 +34,19 @@
|
||||
- Тесты в `tests/`, запуск из корня worktree. Внешних сервисов нет: Jira и хаб заменяют фейки `tests/fake_jira.py` и `tests/fake_hub.py`.
|
||||
- `tests/_common.py` — общая настройка: путь к `src`, `SETTINGS` (как их отдаёт `/agent/settings`), `jira_cfg()`, `no_sleep()`.
|
||||
Паузы в тестах отключаются через `ZERO_PACING` и `no_sleep`.
|
||||
- Для каждого типа команды — свой набор: `test_executor_fields.py`, `test_executor_links.py`, `test_refresh.py`;
|
||||
цикл и восстановление — `test_runner.py`; журнал — `test_journal.py`; HTTP и 429 — `test_clients.py`.
|
||||
- Тесты разбиты по областям, а не по типам команд: `test_executor_fields.py` (`ensure_issue`, `ensure_fields`, `ensure_comment`),
|
||||
`test_executor_links.py` (`ensure_status`, `ensure_link`, `ensure_sprint`), `test_refresh.py` (`refresh`),
|
||||
`test_runner.py` (цикл и восстановление), `test_journal.py` (журнал), `test_clients.py` (HTTP и 429).
|
||||
- Golden-фикстур пока нет: каждый тест строит сценарий в коде.
|
||||
|
||||
## Первая подсистема
|
||||
Исполнитель команд и цикл агента (спека `agent/spec.md`, `commands/spec.md`) — реализованы целиком: все типы команд,
|
||||
журнал, восстановление после перезапуска, CLI `run|check|prune`. Задача 7 плана — документация и проверка совместимости с 3.9.
|
||||
журнал, восстановление после перезапуска, CLI `run|check|prune`.
|
||||
План и спека живут в `jira-hub`: `openspec/changes/bridge-core/` и `docs/superpowers/plans/2026-10-11-bridge-core-hub.md`.
|
||||
|
||||
## OpenSpec и superpowers
|
||||
- Вход в любую задачу — superpowers:brainstorming. Skills openspec-propose и openspec-explore сами по себе не запускать.
|
||||
- Когда brainstorming классифицировал задачу как architectural, структуру change создать через `openspec new change <id>` (или `/opsx:propose <id>`), а содержимое proposal.md, specs/ и design.md написать по итогам brainstorming. tasks.md из OpenSpec не заполнять — задачи живут в плане superpowers.
|
||||
- `/opsx:apply` не использовать: исполнение идёт через writing-plans и SDD/executing-plans.
|
||||
- `openspec archive <id>` — после merge PR, как часть чеклиста закрытия.
|
||||
- Хук require-plan защищает любой каталог `src/` на любой глубине. Если код лежит иначе — перечислить каталоги (префиксы от корня, по одному в строке) в `.claude/code-paths`.
|
||||
|
||||
22
README.md
22
README.md
@ -15,7 +15,9 @@
|
||||
- `hub_token` — агентский токен из `jira-hub tokens` на Mac mini;
|
||||
- `jira.base_url` — адрес Jira банка;
|
||||
- `jira.auth` — `{"type": "basic", "user": ..., "password": ...}` или `{"type": "bearer", "token": ...}`;
|
||||
- `verify_ssl`, `ca_bundle` — при корпоративном сертификате (см. ограничение 3 ниже).
|
||||
- `verify_ssl`, `ca_bundle` — при корпоративном сертификате (см. ограничение 3 ниже);
|
||||
- `timeout` — таймаут запроса в секундах (по умолчанию 60);
|
||||
- `poll_seconds` — пауза между опросами хаба, когда команд нет (по умолчанию 5).
|
||||
3. `agent.json` содержит учётные данные Jira. Никуда не копировать и никуда не отправлять, кроме этой виртуалки.
|
||||
Хаб получает от агента только результаты команд и состояние задач, без паролей и токенов Jira.
|
||||
|
||||
@ -28,7 +30,14 @@
|
||||
python3 agent.py check
|
||||
```
|
||||
|
||||
В норме печатает две строки: `хаб: доступен, настройки v<N>, проект <KEY>` и `Jira: доступен, пользователь <login>`.
|
||||
В норме печатает две строки с префиксом времени `[ЧЧ:ММ:СС]`, например:
|
||||
|
||||
```
|
||||
[10:42:17] хаб: доступен, настройки v3, проект AURORA
|
||||
[10:42:18] Jira: доступен, пользователь ivanov
|
||||
```
|
||||
|
||||
(`хаб: доступен, настройки v<N>, проект <KEY>` и `Jira: доступен, пользователь <login>`).
|
||||
Код выхода 0. Если хаб или Jira недоступны, строка содержит `НЕДОСТУПЕН` и текст ошибки, код выхода 1.
|
||||
Команда ничего не пишет в Jira.
|
||||
|
||||
@ -121,8 +130,8 @@ python3 agent.py prune
|
||||
- **Одна команда в полёте.** Агент берёт следующую команду, только когда предыдущая выполнена и отчёт подтверждён.
|
||||
- **Отчёт до подтверждения.** Отчёт повторяется каждые 10 с, пока хаб не подтвердит. Ответы 404/409/422 хаб
|
||||
выдаёт, когда команда уже отменена или удалена: агент считает её закрытой и не зацикливается.
|
||||
- **429 и 503.** Агент ждёт `Retry-After` из ответа Jira и повторяет запрос, до 5 попыток. Если заголовка нет,
|
||||
ждёт 60 с, умноженные на номер попытки. Число ожиданий идёт в `rate_limited` отчёта.
|
||||
- **429 и 503.** Агент ждёт `Retry-After` из ответа Jira и повторяет запрос: до 5 запросов, то есть не более 4 ожиданий;
|
||||
на пятой неудаче — ошибка команды. Если заголовка нет или он в формате HTTP-date (не разбирается), ждёт 60 с, умноженные на номер попытки. Число ожиданий идёт в `rate_limited` отчёта.
|
||||
- **Версия.** Константа `AGENT_VERSION` в `agent.py` (сейчас 1) отправляется в каждом `claim`.
|
||||
Если хаб назначил `min_agent_version` выше, он пишет в `agent_status.warning`: «обновите агента»; команды
|
||||
при этом выдаются по-прежнему.
|
||||
@ -160,5 +169,6 @@ python3 agent.py prune
|
||||
Отсутствующие ключи при `refresh` по `keys` попадают в `result.missing` (не больше 50).
|
||||
6. **Сравнение описания в `ensure_fields` точное.** Если Jira нормализует переводы строк (CRLF), будут лишние
|
||||
записи. Наблюдать на реальной Jira.
|
||||
7. **429/503 без потолка.** Агент ждёт `Retry-After` сколько бы он ни был (без верхней границы), до 5 попыток.
|
||||
Длинный `Retry-After` держит очередь.
|
||||
7. **429/503 без потолка.** Агент ждёт `Retry-After` в секундах сколько бы он ни был (без верхней границы): не более 4 ожиданий,
|
||||
на пятой неудаче — ошибка. Длинный `Retry-After` держит очередь. Формат HTTP-date в `Retry-After` не разбирается:
|
||||
тогда ждётся 60 с × номер попытки.
|
||||
|
||||
@ -4,6 +4,10 @@ import unittest
|
||||
|
||||
from _common import SRC
|
||||
|
||||
# Ограничение проверки: ast.parse(feature_version=(3, 9)) ловит синтаксис 3.10+ (match и т. п.) и сторонние
|
||||
# импорты; API и конструкции, новые в 3.9 (например, `X | Y` в аннотациях), не проверяет. Их подтверждает только
|
||||
# прогон на /usr/bin/python3 (3.9.6).
|
||||
|
||||
|
||||
class Py39Test(unittest.TestCase):
|
||||
def test_agent_parses_as_python_39(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user