docs(openspec): agent-self-update — сигналы run.py и выход 0 без Ctrl-C (R-20), рулинги R-19…R-21 (#22)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3a4fed94ff
commit
ed9c32a739
@ -110,11 +110,14 @@
|
||||
15. **Дочерний процесс.** `[sys.executable, "-u", <каталог>/agent.py, "run", *аргументы]` с переменной окружения
|
||||
`JIRA_AGENT_LAUNCHER=<LAUNCHER_VERSION>`; stdout/stderr наследуются (лог агента и запускателя — в одном месте).
|
||||
Агент передаёт `launcher_version` в `claim`. Строки запускателя — с префиксом «run:» и временем, как у агента.
|
||||
16. **Сигналы.** SIGINT запускатель игнорирует (Ctrl-C в терминале и так приходит дочернему процессу — общая группа).
|
||||
16. **Сигналы.** SIGINT при живом агенте запускатель только запоминает как «остановил человек» (Ctrl-C в терминале и так
|
||||
приходит дочернему процессу — общая группа); без агента (пауза перед перезапуском) — выход. После сигнала остановки
|
||||
новый агент не запускается.
|
||||
SIGTERM (`kill`, `launchctl unload`) пересылается дочернему процессу; повторный SIGTERM — пересылается снова
|
||||
(агент выходит немедленно, 130). После выхода дочернего процесса по сигналу запускатель выходит.
|
||||
17. **Коды выхода дочернего процесса:**
|
||||
- `0` или `130` — остановка человеком: запускатель выходит с тем же кодом;
|
||||
- `0`, `130` или `-SIGINT` после Ctrl-C (или SIGTERM запускателю) — остановка человеком: запускатель выходит с тем
|
||||
же кодом; те же коды без сигнала запускателю — падение (R-20);
|
||||
- `75` — обновление: если `update.json` = `staged` и sha256 `agent.py.new` совпадает — копия `agent.py` в
|
||||
`agent.py.prev` (временный файл + `os.replace`), затем `os.replace(agent.py.new, agent.py)` (файл `agent.py`
|
||||
существует всегда), `update.json` = `trial` `{from_version, to_version, sha256, at}`, запуск новой версии.
|
||||
@ -192,3 +195,6 @@
|
||||
| R-16 (design #15) | 2026-10-14 | stdout/stderr дочернего процесса наследуются, в `rolled_back` — только код и время | трейсбек остаётся в логе агента; захват вывода усложняет запускатель | причину отката видно в логе на виртуалке, в хабе — только код |
|
||||
| R-17 (design #13) | 2026-10-14 | Агент — версия 5, `min_agent_version` не поднимается | v4 продолжает работать до ручного обновления | нет |
|
||||
| R-18 (design #1) | 2026-10-14 | Публикация через CLI хаба, не через MCP | публикация ставит код на банковскую виртуалку — только явной командой в терминале | нет |
|
||||
| R-19 (агент, исполнение) | 2026-10-14 | `tests/test_folder.py::test_version_is_4` переименован в `test_version_is_5` (AGENT_VERSION = 5) | план не учёл старый тест версии; спека требует v5 | нет |
|
||||
| R-20 (design #16, #17) | 2026-10-14 | Выход агента с 0/130 считается остановкой человеком, только если запускатель сам получил SIGINT/SIGTERM; иначе — падение (в `trial` — откат, вне — перезапуск с паузой); Ctrl-C при выходе с 75 — подмена и выход, `trial` при следующем старте; агент, получивший Ctrl-C во время подготовки, выходит с 0 | финальное ревью агента I-1: версия, сама вышедшая с 0, останавливала мост без отката (под launchd — вечный цикл `trial`); Ctrl-C в терминале запускатель получает всегда (общая группа) | `kill <pid агента>` теперь перезапускает агента — останавливать нужно `run.py` (README) |
|
||||
| R-21 (финальное ревью) | 2026-10-14 | Находка M-1 ревью агента (отрицательный `sleep` в `pause` роняет запускатель) повышена до Important и исправлена | `run.py` обновляется вручную, падение запускателя останавливает мост до человека | нет |
|
||||
|
||||
@ -88,14 +88,18 @@ README агента SHALL описывать: первую установку (
|
||||
`python3 run.py [аргументы]` SHALL работать с файлами в каталоге самого `run.py` (`agent.py`, `agent.py.new`,
|
||||
`agent.py.prev`, `update.json`) и запускать дочерним процессом `agent.py run` с переданными аргументами, переменной
|
||||
окружения `JIRA_AGENT_LAUNCHER = LAUNCHER_VERSION` и унаследованными stdout/stderr. Запускатель SHALL брать
|
||||
неблокирующую блокировку `run.py.lock`; занята — «запускатель уже работает», код 1. SIGINT запускатель SHALL
|
||||
игнорировать, SIGTERM — пересылать дочернему процессу.
|
||||
неблокирующую блокировку `run.py.lock`; занята — «запускатель уже работает», код 1. SIGINT при живом дочернем процессе
|
||||
запускатель SHALL только запоминать как остановку человеком (Ctrl-C получает и агент), без дочернего процесса (пауза
|
||||
перед перезапуском) — завершаться; SIGTERM — пересылать дочернему процессу. После сигнала остановки запускатель MUST NOT
|
||||
запускать агента снова.
|
||||
|
||||
По коду выхода дочернего процесса:
|
||||
- `0` или `130` — запускатель завершается с тем же кодом;
|
||||
- `0`, `130` или завершение по SIGINT после Ctrl-C (или после SIGTERM запускателю) — запускатель завершается с тем же
|
||||
кодом; те же коды без сигнала запускателю — падение;
|
||||
- `75` — при `update.json` = `staged` и совпадении sha256 `agent.py.new`: копия `agent.py` в `agent.py.prev`, атомарная
|
||||
замена `agent.py` на `agent.py.new`, `update.json` = `trial`, запуск новой версии; иначе `agent.py.new` удаляется,
|
||||
`update.json` = `rejected` «файл изменился после проверки», запуск текущей версии;
|
||||
`update.json` = `rejected` «файл изменился после проверки», запуск текущей версии; если перед этим был Ctrl-C —
|
||||
после подмены запускатель завершается, пробный период начнётся при следующем старте;
|
||||
- иной код при `update.json` = `trial` — откат; иначе — перезапуск той же версии с паузой 5 с, удваиваемой до 300 с
|
||||
при каждом следующем падении и сбрасываемой после 10 минут работы.
|
||||
|
||||
@ -119,6 +123,10 @@ README агента SHALL описывать: первую установку (
|
||||
- **THEN** запускатель посылает SIGTERM, через 60 с при необходимости SIGKILL, делает откат с причиной «не вышла на связь
|
||||
за 10 мин»
|
||||
|
||||
#### Scenario: Новая версия сама вышла с кодом 0
|
||||
- **WHEN** `update.json` = `trial` для v7, дочерний процесс вышел с кодом 0, сигналов запускатель не получал
|
||||
- **THEN** откат на v6 с причиной «код 0 через <S> с», как при падении
|
||||
|
||||
#### Scenario: Падение после подтверждения
|
||||
- **WHEN** `update.json` = `ok`, агент дважды подряд упал с кодом 1, проработав меньше минуты
|
||||
- **THEN** запускатель перезапускает ту же версию через 5 с, затем через 10 с; отката нет
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user