Документация и e2e: хаб переименован в sdlc-hub (#5) #6

Merged
aep merged 1 commits from feat/5-sdlc-docs into main 2026-10-24 15:15:16 +03:00
5 changed files with 18 additions and 16 deletions

View File

@ -1,7 +1,7 @@
# Архитектура
Агент — один файл `src/agent.py` и запускатель `src/run.py` (Python 3.9, только стандартная библиотека). Тесты в
`tests/` работают на фейках хаба и Eva. Спека: `../jira-hub/openspec/changes/wiki-module/`; решения агента:
`tests/` работают на фейках хаба и Eva. Спека: `../sdlc-hub/openspec/changes/wiki-module/`; решения агента:
`openspec/changes/eva-agent-mvp/design.md`. Общие части — копия jira-agent v14 (`../jira-agent/ARCHITECTURE.md`).
## Разделы файла `src/agent.py`
@ -39,7 +39,7 @@
- Тесты не ходят во внешние сервисы.
## Сквозной прогон
`scripts/e2e-hub.sh`: настоящий хаб (`jira-hub serve` из worktree `jira-hub/.wt/wiki`, временный `JIRA_HUB_HOME`, свободный
`scripts/e2e-hub.sh`: настоящий хаб (`sdlc-hub serve` из основного checkout `sdlc-hub`, временный `SDLC_HUB_HOME`, свободный
порт) + `scripts/fake_eva_serve.py` + `agent.py run --once` по HTTP. Живой хаб и его данные не затрагиваются.
## Открытые вопросы

View File

@ -1,11 +1,11 @@
# eva-agent
## Что это
Клиент модуля wiki хаба (sdlc-hub, `../jira-hub`) для виртуалки с доступом к Eva банка. Опрашивает хаб, по командам
Клиент модуля wiki хаба (sdlc-hub, `../sdlc-hub`) для виртуалки с доступом к Eva банка. Опрашивает хаб, по командам
`wiki_sync` (выгрузить поддерево страниц с корня) и `wiki_fetch` (скачать вложение) читает Eva и отдаёт данные хабу;
в Eva ничего не пишет. Главный сценарий: хаб ставит `wiki_sync` с кодом корня, агент обходит дерево страниц, шлёт
страницы пачками в стадию хаба и отчитывается списком кодов.
Спека и дизайн: `../jira-hub/openspec/changes/wiki-module/` (hub#91, PR hub#92); решения агента —
Спека и дизайн: `../sdlc-hub/openspec/changes/wiki-module/` (hub#91, PR hub#92); решения агента —
`openspec/changes/eva-agent-mvp/design.md`. Issue агента — aep/eva-agent#1.
## Стек и ограничения
@ -32,7 +32,7 @@
ресурсы (так проверяем перед коммитом).
- `/usr/bin/python3 src/agent.py check` — доступность хаба и Eva (`CmfDocument.list`, 1 запись), без записи; код 0 или 3.
- `/usr/bin/python3 src/agent.py run --once` — выполнить выданное и выйти при первом пустом claim.
- `bash scripts/e2e-hub.sh` — сквозной прогон с тестовым хабом из `../../../jira-hub/.wt/wiki` (временный `JIRA_HUB_HOME`, свободный порт, фейковая Eva); «e2e: ok». Живой хаб не трогать.
- `bash scripts/e2e-hub.sh` — сквозной прогон с тестовым хабом из основного checkout `sdlc-hub` workspace (временный `SDLC_HUB_HOME`, свободный порт, фейковая Eva); «e2e: ok». Живой хаб не трогать.
- `/usr/bin/python3 src/agent.py` — основной цикл (нужен `agent.json` рядом с `agent.py`).
- `/usr/bin/python3 src/agent.py prune` — очистка журнала (при работающем агенте откажет).
- `/usr/bin/python3 src/agent.py selftest` — версия + `check`; код 0 или 3.
@ -49,8 +49,8 @@
## Первая подсистема
MVP агента: каркас с общими частями (задача 1 плана `docs/superpowers/plans/`), затем клиент Eva, обход дерева,
`wiki_sync`, `wiki_fetch`, установка и живая проверка. Версия агента — 1. Выкатка: `uv run --project ../jira-hub
jira-hub agent publish --module wiki src/agent.py` (из основного checkout; без `--module` версия уйдёт агенту jira);
`wiki_sync`, `wiki_fetch`, установка и живая проверка. Версия агента — 1. Выкатка: `uv run --project ../sdlc-hub
sdlc-hub agent publish --module wiki src/agent.py` (из основного checkout; без `--module` версия уйдёт агенту jira);
порог — настройка хаба `wiki_min_agent_version`; токен — «агент wiki».
## OpenSpec и superpowers

View File

@ -12,7 +12,7 @@ Eva (`wiki_sync`) и скачивает вложения (`wiki_fetch`); в Eva
2. Положить в него `agent.py` и `run.py` (из `src/`) и `agent.json` (из `agent.example.json`):
- `hub_url` — тот же `folder:<путь>`, что у jira-agent (общая папка с хабом; при VPN виртуалка не видит Mac mini по
сети), либо `http://<хост>:8790`;
- `hub_token` — строка «агент wiki» из `jira-hub tokens` (токен именно агента wiki, не jira и не клиентский);
- `hub_token` — строка «агент wiki» из `sdlc-hub tokens` (токен именно агента wiki, не jira и не клиентский);
- `eva.base_url` — адрес Eva **только origin**: схема, хост и порт, без пути и без `/` в конце, например
`https://eva.example.ru`. Агент сам добавляет к нему `/api/` (JSON-RPC), `/files/…` (вложения) и
`/project/Document/<код>` (ссылка на страницу); «свой» адрес вложения сравнивается с ним же, поэтому путь в
@ -69,7 +69,7 @@ launchctl unload ~/Library/LaunchAgents/ru.aepif.eva-agent.plist
Из основного checkout репозитория (не из worktree), при поднятой версии `AGENT_VERSION` в `src/agent.py`:
uv run --project ../jira-hub jira-hub agent publish --module wiki src/agent.py
uv run --project ../sdlc-hub sdlc-hub agent publish --module wiki src/agent.py
Агент подтянет её сам (`auto_update`); настройку хаба `wiki_min_agent_version` (не `min_agent_version` — та у агента
jira) поднимать после того, как `agent_status` покажет новую версию агента wiki.
@ -79,6 +79,6 @@ jira) поднимать после того, как `agent_status` покаже
Настройки — `src/agent.example.json`. Тесты: `/usr/bin/python3 -W error::ResourceWarning -m unittest discover -s tests -t .`
Сквозной прогон с настоящим хабом и фейковой Eva: `bash scripts/e2e-hub.sh` (печатает «e2e: ok», ~1 мин). Хаб берётся из
`../../../jira-hub/.wt/wiki` (переменная `HUB_SRC`), запускается на свободном порту с временным `JIRA_HUB_HOME`;
основного checkout `sdlc-hub` workspace (переменная `HUB_SRC`), запускается на свободном порту с временным `SDLC_HUB_HOME`;
живой хаб не затрагивается. Проверяет: проект с `wiki_root`, `wiki_sync` на 5 страниц, Markdown со ссылкой
`attachment:<id>`, `wiki_fetch` вложения и его содержимое.

View File

@ -1,17 +1,19 @@
#!/usr/bin/env bash
# Сквозной прогон eva-agent с настоящим хабом (модуль wiki) и фейковой Eva. Печатает «e2e: ok».
# Хаб — ТОЛЬКО из worktree jira-hub/.wt/wiki, ТОЛЬКО с временным JIRA_HUB_HOME и портом не 8790; живой хаб не трогаем.
# Хаб — код из HUB_SRC (по умолчанию основной checkout sdlc-hub workspace), ТОЛЬКО с временным SDLC_HUB_HOME и портом
# не 8790; живой хаб и его данные не трогаем.
set -euo pipefail
HERE="$(cd "$(dirname "$0")/.." && pwd)"
HUB_SRC="${HUB_SRC:-$HERE/../../../jira-hub/.wt/wiki}"
BRIDGE="$(cd "$(git -C "$HERE" rev-parse --path-format=absolute --git-common-dir)/../.." && pwd)" # workspace jira-bridge (из worktree тоже)
HUB_SRC="${HUB_SRC:-$BRIDGE/sdlc-hub}"
HUB_SRC="$(cd "$HUB_SRC" && pwd)"
PORT="${E2E_PORT:-$(/usr/bin/python3 -c 'import socket; s = socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1]); s.close()')}"
[ "$PORT" != "8790" ] || { echo "e2e: порт 8790 занят живым хабом" >&2; exit 2; }
TMP="$(mktemp -d)"
export JIRA_HUB_HOME="$TMP/hub-home"
mkdir -p "$JIRA_HUB_HOME"
export SDLC_HUB_HOME="$TMP/hub-home"
mkdir -p "$SDLC_HUB_HOME"
PIDS=()
stop_tree() { # остановить процесс и его детей (uv run запускает хаб дочерним процессом)
local p="$1" c
@ -32,7 +34,7 @@ cleanup() {
}
trap cleanup EXIT INT TERM
hub() { uv run --project "$HUB_SRC" --no-sync jira-hub "$@"; }
hub() { uv run --project "$HUB_SRC" --no-sync sdlc-hub "$@"; }
fail() { echo "e2e: ОШИБКА — $*" >&2; echo "--- лог хаба ---" >&2; tail -n 30 "$TMP/hub.log" >&2 || true; exit 1; }
jget() { /usr/bin/python3 -c 'import json,sys; d=json.load(sys.stdin)
for k in sys.argv[1].split("."):

View File

@ -1,6 +1,6 @@
{
"hub_url": "folder:/путь/к/общей/папке/jira-bridge",
"hub_token": "токен агента wiki из `jira-hub tokens`",
"hub_token": "токен агента wiki из `sdlc-hub tokens`",
"eva": {
"base_url": "https://eva.example.ru",
"token": "токен Eva (Bearer)"