docs(agents): HUB-1 — зелёный main и P0 из аудита для серверной сессии
Задание для серверной сессии Claude (не для agy): довести main до зелёного и закрыть P0 аудита Hermes Hub. Шаг 1 плана слияния — стабильный Hermes как эталон переноса. Причина красного main найдена ревьюером в логе CI, а не по аудиту: - test_a37_isolation_guards.py:394 — WorkspaceBoundaryGuard пропускает rm -rf $HOME/.hermes на Windows (провал security-инварианта); - verify_multi_provider_router.py:63 — UnicodeEncodeError на cp1252 при печати русского текста. Остальные P0 (Release Gate hash, publication gate fail-open, /api/action CSRF) — подтвердить исполнением перед правкой. pricing safe_dump — реальный, в P1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
144f6a5d59
commit
93da1b22fd
1 changed files with 150 additions and 0 deletions
150
agents/inbox/2026-09-02-HUB1-audit-p0-green-main.md
Normal file
150
agents/inbox/2026-09-02-HUB1-audit-p0-green-main.md
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
# Задание HUB-1: зелёный main и P0 из аудита Hermes Hub
|
||||||
|
|
||||||
|
## Для кого
|
||||||
|
**Серверная сессия Claude (пользователь `ochenstarik`), не для agy.** Это работа
|
||||||
|
исполнителя-Claude: правка кода, прогон, пуш. Ревьюер (сессия на ПК) принимает.
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
2026-09-02.
|
||||||
|
|
||||||
|
## База
|
||||||
|
`origin/main` (`144f6a5`).
|
||||||
|
|
||||||
|
```
|
||||||
|
git fetch origin --prune
|
||||||
|
git checkout -b hub/audit-p0-green-main origin/main
|
||||||
|
```
|
||||||
|
|
||||||
|
В `main` напрямую не пушить. **Координация:** над `main` работают две сессии.
|
||||||
|
Перед пушем — `git fetch` и `git log --oneline origin/main`; при расхождении
|
||||||
|
перенести правки поверх, как это уже делалось.
|
||||||
|
|
||||||
|
## Зачем
|
||||||
|
|
||||||
|
По решению о слиянии (`docs/research/kagent-merge-decision.md`) шаг 1 —
|
||||||
|
**Hermes довести до зелёного и стабильного**, потому что он служит эталоном
|
||||||
|
переноса, а сломанный эталон портировать нельзя. Сейчас `main` красный. Полный
|
||||||
|
аудит — на рабочем столе владельца (`HERMES_HUB_FULL_AUDIT_2026-09-02.md`);
|
||||||
|
здесь только то, что подтверждено исполнением.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Что ревьюер уже проверил — заново не выяснять
|
||||||
|
|
||||||
|
### CI на main красный. Причина — два дефекта, оба видны в логе последнего прогона
|
||||||
|
|
||||||
|
**1. Security-инвариант A37 не держится на Windows.**
|
||||||
|
`tests/test_a37_isolation_guards.py:394` падает:
|
||||||
|
|
||||||
|
```
|
||||||
|
AssertionError: команда со стильдой прошла мимо защиты: rm -rf $HOME/.hermes (OK)
|
||||||
|
assert not True
|
||||||
|
```
|
||||||
|
|
||||||
|
WorkspaceBoundaryGuard пропускает разрушительную команду с `$HOME`, потому что
|
||||||
|
раскрытие переменных и нормализация путей на Windows и Linux различаются. Это
|
||||||
|
не косметика — это граница вокруг агентских shell-действий. Пока она работает
|
||||||
|
по-разному на поддерживаемых системах, sandbox нельзя считать доказанным.
|
||||||
|
|
||||||
|
**2. Windows UTF-8 роняет verification-скрипт.**
|
||||||
|
`scripts/verify_multi_provider_router.py:63`:
|
||||||
|
|
||||||
|
```
|
||||||
|
UnicodeEncodeError: 'charmap' codec can't encode characters ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Скрипт печатает русский текст (`[PASS] Чистая конфигурация...`), а консоль
|
||||||
|
Windows в CI — cp1252. Падает `print`, не логика.
|
||||||
|
|
||||||
|
Красные джобы: `Headless Run (no GUI dependencies)` и
|
||||||
|
`Clean Windows Runner Test`.
|
||||||
|
|
||||||
|
### Баг pricing fallback (P2, но реальный)
|
||||||
|
|
||||||
|
`src/antigravity_provider/router/telemetry_service.py:164`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
data = yaml.safe_dump(p.read_text(encoding="utf-8"))
|
||||||
|
if isinstance(data, dict) and "pricing" in data: # всегда False
|
||||||
|
```
|
||||||
|
|
||||||
|
`safe_dump` вместо `safe_load` — таблица цен из `pricing.yaml` не грузится
|
||||||
|
никогда, и `except: pass` это глушит. Должно быть `safe_load`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## P0-1. Зелёный main (это первично)
|
||||||
|
|
||||||
|
1. **Исправить UTF-8 в verification-скрипте**: принудительный UTF-8 вывода
|
||||||
|
(`PYTHONUTF8`, `PYTHONIOENCODING=utf-8`, реконфигурация `sys.stdout`, либо
|
||||||
|
безопасное кодирование). Кросс-платформенно, проверяемо на обеих системах.
|
||||||
|
2. **Исправить WorkspaceBoundaryGuard** единым конвейером: классификация
|
||||||
|
диалекта shell → раскрытие только распознанных переменных → нормализация
|
||||||
|
разделителей → разрешение `$HOME`/`%USERPROFILE%` → канонизация пути →
|
||||||
|
сравнение с защищёнными корнями → **fail closed**. Одинаковый тест-набор для
|
||||||
|
Windows и Linux; `test_a37_isolation_guards` должен ловить `rm -rf $HOME/...`
|
||||||
|
на обеих системах.
|
||||||
|
3. **Проверка — по зелёному CI**, а не локально: локальный прогон на Linux эти
|
||||||
|
две джобы не воспроизводит. Довести оба Windows-джоба до зелёного.
|
||||||
|
|
||||||
|
## P0-2. Остальные P0 аудита — подтвердить исполнением ПЕРЕД правкой
|
||||||
|
|
||||||
|
Ревьюер их не проверял. По каждому: сначала воспроизвести, потом чинить. Не
|
||||||
|
чинить со слов аудита.
|
||||||
|
|
||||||
|
1. **Release Gate заявляет проверку хеша, которой не было** — частичный HTTP
|
||||||
|
Range, но `PACKAGE_HASH_VERIFIED=True` без полного SHA-256. Прочитать
|
||||||
|
`scripts/release_gate.py`, подтвердить, затем считать полный хеш или брать
|
||||||
|
достоверный digest из release API.
|
||||||
|
2. **Publication gate fail-open** — 404/сеть/отсутствие пакета возвращаются как
|
||||||
|
PASS. Разделить Offline Gate (тесты, updater, статика, сборка) и Publication
|
||||||
|
Gate (релиз есть, ассеты есть, digest сверен, скачивание прошло).
|
||||||
|
3. **localhost `/api/action` без CSRF/Origin** — на loopback токен не требуется,
|
||||||
|
а действие меняет состояние. Проверить, затем: bootstrap-токен, проверка
|
||||||
|
`Origin`/`Sec-Fetch-Site`, авторизация небезопасных методов.
|
||||||
|
|
||||||
|
## P1. После зелёного main
|
||||||
|
|
||||||
|
1. **Zip-slip в updater**: распаковка обязана проверять каждый путь
|
||||||
|
(`resolved.is_relative_to(staging)`), запрет абсолютных путей, `..`, symlink,
|
||||||
|
device.
|
||||||
|
2. **pricing fallback**: `safe_load` вместо `safe_dump` (см. выше).
|
||||||
|
3. **CI-матрица Windows + Linux**: сейчас Linux-джоба нет, а проект на Linux и
|
||||||
|
активно получает Linux-фиксы.
|
||||||
|
4. Прочее из аудита (failover error policy, `uv sync --frozen`, лишний `web`
|
||||||
|
extra, secret-scan шире) — отдельными заданиями, не в этом.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ограничения
|
||||||
|
|
||||||
|
- Правки ревьюера из `main` не откатывать.
|
||||||
|
- Фронтенд без npm/сборки/фреймворков — `docs/web-api/CONTRACT.md` §1.
|
||||||
|
- Проверку SHA-256 и список разрешённых адресов обновления не ослаблять.
|
||||||
|
- Учётные данные и `~/.hermes/agy_profiles/` не трогать.
|
||||||
|
- Версию `0.1.3` не понижать.
|
||||||
|
- Правило честности: неизмеренное — `Н/Д` с причиной.
|
||||||
|
|
||||||
|
## Критерии приёмки
|
||||||
|
|
||||||
|
1. Ветка в `origin`, `git status` чист.
|
||||||
|
2. **Оба Windows-джоба CI зелёные** — ссылка на зелёный прогон в отчёте.
|
||||||
|
3. `test_a37_isolation_guards` ловит `rm -rf $HOME/...` на Windows и Linux;
|
||||||
|
guard fail-closed.
|
||||||
|
4. verification-скрипт не падает на cp1252.
|
||||||
|
5. Остальные P0 либо исправлены с доказательством, либо явно помечены как
|
||||||
|
отложенные с причиной.
|
||||||
|
6. `ruff check .` чисто; локальный прогон Linux зелёный; число тестов не меньше
|
||||||
|
текущего.
|
||||||
|
7. Отчёт: `START_HEAD`, `FINAL_HEAD`, `origin/main`, `git status`,
|
||||||
|
`X passed / Y skipped / Z failed`, ссылка на зелёный CI.
|
||||||
|
|
||||||
|
## Главное
|
||||||
|
|
||||||
|
Первично — зелёный main, и обе причины уже найдены: security-guard на Windows и
|
||||||
|
UTF-8 в verification. Остальные P0 аудита — только после подтверждения
|
||||||
|
исполнением. Это фундамент под слияние: пока Hermes красный и его sandbox-guard
|
||||||
|
дырявый на одной из систем, переносить его поведение в KAgent нельзя.
|
||||||
|
|
||||||
|
## Порядок сдачи
|
||||||
|
Передать точный `FINAL_COMMIT_SHA` и ссылку на зелёный прогон CI.
|
||||||
Loading…
Reference in a new issue